Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How to send a number to webworker ?
How to receive a number in webworker ?
if possible, How to do this without using json or javascript Object, because using it will add extra line of code ..
EDIT :
ew i got many downvote without knowing why .. i explain what i try to do..
i try to create timer in webworker
if i send string "start" to webworker, webworker will begin the
interval( the timer )
if i send a number to webworker, webworker will set the duration of
interval
but i don't know how to send a number,
i knew argument passed to webworker should be a string, i already read few tutorial,
but i still don't understand what to do so my webworker can recognize a number..
because i try parseInt() and is not work ..
here's my code
in HTML
window.onload = function(){
var worker = new Worker("Thread.js");
worker.postMessage("1500"); //set duration of interval
worker.postMessage("start"); //start the interval
worker.onmessage = function(e){
document.body.innerHTML += '<p> worker receive: '+e.data+'</p>';
}
worker.onerror = function(e){
document.body.innderHTML += "<p> worker error"+e.data+"</p>";
}
}
Thread.js
onmessage = function(e){
var msg = e.data ;
var timer;
var duration = 1000; //default duration
try{
var number = parseInt(msg);
msg = number;
}catch(e){
}
//start the interval
if(msg === "start"){
timer = setInterval(function(){
postMessage( "lalala" );
}, duration);
}
else if(msg === "stop"){
clearInterval(timer);
}
//set duration
else if(!isNaN(msg)){
duration = msg;
}
}
That doesn't work because parseInt doesn't throw an Error, it returns NaN (Not a Number).
You also have another bug: you need to declare timer and duration outside onmessage if you want both to persist between two messages.
Note that changing duration won't affect the interval unless you restart it.
var timer;
var duration = 1000;
onmessage = function(e) {
var msg = e.data ;
var number = parseInt(msg);
if(msg === "start") {
timer = setInterval(function() {
postMessage( "lalala" );
}, duration);
} else if(msg === "stop") {
clearInterval(timer);
} else if(!isNaN(msg)) {
duration = number;
}
};
Related
I need to do some API call and also DB manipulation during rendering of messages for a function.
I have these long function, let's call it alongFunction
function longFunction(message, item) {
var win = lib.gui.window.get(id);
var msg = message.msg;
var id = message.id;
var direction = message.direction;
//inside are basically some DOM manipulation
//around 10 lines here
//and also there are rendering/misc code
//around 10 lines here
//then we are rendering some messages here:
var msgDiv = $('<div>'), msgTsDiv = $('<div>');
msgDiv.addClass('chat '+direction);
msgDiv.attr('id', id);
if(direction == 'in') {
//I need to add a hook here to do API call, but it takes some time
msgDiv.html('<div class="message in">'+message+'</div>');
} else {
msgDiv.html('<div class="message out">'+message+'</div>');
}
//NEW CODE ADDED HERE: Check below pls
//and because JS is async, it just passes these codes
//around 50 codes for manipulation etc...
if(message.isReceived()) {
msgDiv.addClass('received');
}
//and some other stuff here...
}
I added at the NEW CODED ADDED HERE these:
function longFunction(message, item) {
var win = lib.gui.window.get(id);
var msg = message.msg;
var id = message.id;
var direction = message.direction;
//inside are basically some DOM manipulation
//around 10 lines here
//and also there are rendering/misc code
//around 10 lines here
//then we are rendering some messages here:
var msgDiv = $('<div>'), msgTsDiv = $('<div>');
msgDiv.addClass('chat');
msgDiv.attr('id', id);
//only translating message coming in
if(direction == 'in') {
getTranslatedMessage(message).then(function(newMessage){
//I need to add a hook here to do API call, but it takes some time
msgDiv.html('<div class="message in">'+newMessage+'</div>');
}).catch(function(error){
if(error) {
msgDiv.html('<div class="message">'+message+'<br>'+error+'</div>');
} else {
msgDiv.html('<div class="message in">'+message+'</div>');
}
});
} else {
msgDiv.html('<div class="message out">'+message+'</div>');
}
//end of translation - UPDATE
//and because JS is async, it just pass these codes
//around 50 codes for manipulation etc...
if(message.isReceived()) {
msgDiv.addClass('received');
}
//and some other stuff here...
}
UPDATE:
I have tried
putting everything into one big callback = but it is not returning any result.
repeat the remaining code by copy-pasting it into the callback and outside = the message printed is not in proper sequence (this function is called in a loop)
Note: The function is a bit long, so I just made a simple version for it
Important: This function is being called in a loop.
Thank you in advance!
I am not familiar with this function, however I am seeing intermittent failures, sometimes the timer function will execute and the newState variable switches, sometimes it doesn't. Please can you check my understanding of what this is doing?
function motionHandler() {
console.log('im in motionhandler func')
var newState = true;
changeAction(newState);
if(this.timer !== undefined) clearTimeout(this.timer);
this.timer = setTimeout(function(){changeAction(!newState);}, this.window_seconds * 1000);
};
From what I understand, when this function executes I set the newState variable to true. I then execute changeAction which sets my motion detector to "true" (motion detected).
I then create a timer. If this.timer has something in it, then clear. I then create a timeout which will countdown from window_seconds * 1000 (ie. 5x1000 milliseconds = 5 seconds). Once that timeout is reached, I will execute the changeAction function and set newState to the opposite of what it currently is?
Assuming all of that is correct, sometimes newState gets reset, other times it doesn't.
I am executing the motionHandler function every time I receive a particular RF code from a transmitter. The timeout is there to reset the motion detector back to false when no codes are received.
The full code is actually a plugin for home bridge, and can be seen here:
https://github.com/mattnewham/homebridge-RFReceiver/blob/master/index.js
This is my first real foray into Javascript/NodeJS so I don't really know how to troubleshoot this (other than my console.logs!)
Full code:
var Service;
var Characteristic;
var rpi433 = require("rpi-433"),
rfSniffer = rpi433.sniffer({
pin: 2, //Snif on GPIO 2 (or Physical PIN 13)
debounceDelay: 1000 //Wait 500ms before reading another code
}),
rfEmitter = rpi433.emitter({
pin: 0, //Send through GPIO 0 (or Physical PIN 11)
pulseLength: 350 //Send the code with a 350 pulse length
});
var debug = require("debug")("RFReceiverAccessory");
var crypto = require("crypto");
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
homebridge.registerAccessory("homebridge-RFReceiver", "RFReceiver", RFReceiverAccessory);
}
function RFReceiverAccessory(log, config) {
this.log = log;
// url info
this.name = config["name"];
this.rfcode = config["rfcode"] || 4;
this.window_seconds = config["window_seconds"] || 5;
this.sensor_type = config["sensor_type"] || "m";
this.inverse = config["inverse"] || false;
}
RFReceiverAccessory.prototype = {
getServices: function() {
// you can OPTIONALLY create an information service if you wish to override
// the default values for things like serial number, model, etc.
var informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Name, this.name)
.setCharacteristic(Characteristic.Manufacturer, "Homebridge")
.setCharacteristic(Characteristic.Model, "RF Receiver")
.setCharacteristic(Characteristic.SerialNumber, "12345");
var service, changeAction;
if(this.sensor_type === "c"){
service = new Service.ContactSensor();
changeAction = function(newState){
service.getCharacteristic(Characteristic.ContactSensorState)
.setValue(newState ? Characteristic.ContactSensorState.CONTACT_DETECTED : Characteristic.ContactSensorState.CONTACT_NOT_DETECTED);
};
} else {
service = new Service.MotionSensor();
changeAction = function(newState){
console.log('changing state');
service.getCharacteristic(Characteristic.MotionDetected)
.setValue(newState);
};
}
function motionHandler() {
console.log('im in motionhandler func')
var newState = true;
changeAction(newState);
if(this.timer !== undefined) clearTimeout(this.timer);
this.timer = setTimeout(function(){changeAction(!newState);}, this.window_seconds * 1000);
};
var code = this.rfcode
var name = this.name
rfSniffer.on('data', function (data) {
console.log('Code received: '+data.code+' pulse length : '+data.pulseLength);
console.log(code);
if(data.code == code){
console.log("Motion Detected In" +name);
motionHandler()};
});
return [informationService, service];
}
};
This question already has an answer here:
recursive clearInterval does not work
(1 answer)
Closed 8 years ago.
I have the following function in javaScript. This function is called when i detect a need to re-load the stylesheet. for example, doe to user language change, so the text won't fit the buttons anymore. The problem is, it gets stuck in the setInterval part. looping into it endlessly. I can see in the chrome debugger that it does get to the clearInterval part - but it wont clear. This function - resetStyle - is only called once.
Can anyone please help?
Thank you!
p.resetStyle = function () {
var that = this;
var oldStylesheet_href = $('#mainStylesheet').attr("href");
var i = oldStylesheet_href.indexOf('lang');
var lastLanguege = oldStylesheet_href.substring(i + 5, i + 7);
var prefix, sufix;
if (lastLanguege === createjs.mainManager.LangString) {
return;
}
prefix = oldStylesheet_href.substring(0, i - 1);
sufix = '&' + oldStylesheet_href.substring(i + 7, oldStylesheet_href.length);
var head = document.getElementsByTagName('head')[0]; // reference to document.head for appending/ removing link nodes
var link = document.createElement('link'); // create the link node
link.setAttribute('id', 'newStylesheet');
link.setAttribute('href', prefix + '&lang=' + createjs.mainManager.LangString + sufix);
link.setAttribute('rel', 'stylesheet');
link.setAttribute('type', 'text/css');
var sheet, cssRules;
// get the correct properties to check for depending on the browser
if ('sheet' in link) {
sheet = 'sheet';
cssRules = 'cssRules';
} else {
sheet = 'styleSheet';
cssRules = 'rules';
}
var timeout_id = setInterval(function () { // start checking whether the style sheet has successfully loaded
try {
if (link[sheet] && link[sheet][cssRules].length) { // SUCCESS! our style sheet has loaded
clearInterval(timeout_id); // clear the counters
clearTimeout(timeout_id);
that.onStyleReset();
}
} catch (e) {} finally {}
}, 10), // how often to check if the stylesheet is loaded
timeout_id = setTimeout(function () { // start counting down till fail
clearInterval(timeout_id); // clear the counters
clearTimeout(timeout_id);
head.removeChild(link); // since the style sheet didn't load, remove the link node from the DOM
that.onStyleReset();
}, 15000);
$('head').append(link);
$('#mainStylesheet').remove();
link.setAttribute('id', 'mainStylesheet');
};
You're reusing the variable timeout_id for two different things (your interval id and your timeout id), so you're overwriting your interval id when you call setTimeout. Change:
var timeout_id = setInterval(...
to:
var interval_id = setInterval(...
and update the variable where you call clearInterval as well: clearInterval(interval_id);
Thank you for taking the time to help me.
I am writing a game where an animated train icon moves along a given path to a destination, pausing at waypoints along the way. This is intended to give the impression of animation.
The game is coded in Facebook Javascript. I need to find a way to make the train icon pause for 1 second before moving on to the next waypoint. I hoped to find a function that would allow me to pause script execution for one second, but nothing like that seems to exist in JS. So I tried setTimeout, but my primary problem with this is twofold:
I need to pass an array into the callback function as an argument, and I can't figure out how to make setTimeout do this.
I finally succeeded in using setTimeout to execute my train animation code for 5 waypoints (I overcame the issue in 1 by using global variables). Unfortunately, it appears that all five calls to setTimeout got queued almost simultaneously, which resulted in waiting one second for the first setTimeout to fire, thenn they all fired at once ruining the illusion of train animation.
I've been battling this problem for six hours straight. It would be wonderful if someone could help me find a solution. Thanks!
Here's the code:
function myEventMoveTrainManual(evt, performErrorCheck) {
if(mutexMoveTrainManual == 'CONTINUE') {
var ajax = new Ajax();
var param = {};
if(evt) {
var cityId = evt.target.getParentNode().getId();
var param = { "city_id": cityId };
}
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data) {
var actionPrompt = document.getElementById('action-prompt');
actionPrompt.setInnerXHTML('<span><div id="action-text">'+
'Train en route to final destination...</div></span>');
for(var i = 0; i < data.length; i++) {
statusFinalDest = data[i]['status_final_dest'];
//pause(1000);
gData = data[i];
setTimeout(function(){drawTrackTimeout()},1000);
if(data[i]['code'] == 'UNLOAD_CARGO' && statusFinalDest == 'ARRIVED') {
unloadCargo();
} else if (data[i]['code'] == 'MOVE_TRAIN_AUTO' || data[i]['code'] == 'TURN_END') {
//moveTrainAuto();
} else {
// handle error
}
mutexMoveTrainManual = 'CONTINUE';
}
}
ajax.post(baseURL + '/turn/move-train-final-dest', param);
}
}
function drawTrackTimeout() {
var trains = [];
trains[0] = gData['train'];
removeTrain(trains);
drawTrack(gData['y1'], gData['x1'], gData['y2'], gData['x2'], '#FF0', trains);
gData = null;
}
Typically this would be done by creating an object (say called myTrain) that has all its own data and methods, then call a myTrain.run mehod that looks to see where the train is. If it's between two stations, it calls itself with setTimeout and say a 50ms delay. When it reaches a station, it calls itself in 1000ms, creating a 1 second pause at the station.
If you queue the setTimeouts all at once, you run the risk of them all being delayed by some other process, then all running at once.
Hey, bit of fun (careful of wrapping). Needed a bit of practice with good 'ole prototype inheritance:
<!-- All the style stuff should be in a rule -->
<div style="position: relative; border: 1px solid blue;">
<div id="redTrain"
style="width:10px;height:10px;background-color:red; position:absolute;top:0px;left:0px;"></div>
</div>
<script type="text/javascript">
// Train constructor
function Train(id) {
this.element = document.getElementById(id);
this.timerId;
}
// Methods
// Trivial getPos function
Train.prototype.getPos = function() {
return this.element.style.left;
}
// Trivial setPos function
Train.prototype.setPos = function(px) {
this.element.style.left = parseInt(px,10) + 'px';
}
// Move it px pixels to the right
Train.prototype.move = function(px) {
this.setPos(px + parseInt(this.getPos(),10));
}
// Recursive function using setTimeout for animation
// Probably should accept a parameter for lag, long lag
// should be a multiple of lag
Train.prototype.run = function() {
// If already running, stop it
// so can interrupt a pause with a start
this.stop();
// Move the train
this.move(5);
// Keep a reference to the train for setTimeout
var train = this;
// Default between each move is 50ms
var lag = 50;
// Pause for 1 second each 100px
if (!(parseInt(this.getPos(),10) % 100)) {
lag = 1000;
}
train.timerId = window.setTimeout( function(){train.run();}, lag);
}
// Start should do a lot more initialising
Train.prototype.start = function() {
this.run();
}
// Stops the train until started again
Train.prototype.stop = function() {
if (this.timerId) {
clearTimeout(this.timerId);
}
}
// Set back to zero
Train.prototype.reset = function() {
this.stop();
this.setPos(0);
}
// Initialise train here
var myTrain = new Train('redTrain');
</script>
<p> </p>
<button onclick="myTrain.start();">Start the train</button>
<button onclick="myTrain.stop();">Stop the train</button>
<button onclick="myTrain.reset();">Reset the train</button>
To pass arguments, this might help you:
setTimeout(function() {
(function(arg1, arg2) {
// you can use arg1 / arg2 here
})('something', 123);
}, 1000);
Or, if you use a defined function:
setTimeout(function() {
someFunction('something', 123);
}, 1000);
It basically starts a timeout; after one second the function is invoked with the specified arguments.
How about using OO principles to simplify the problem? Create an "object" Train which has the following methods:
//train obj
function Train(){
this.isOnWaypoint = function(){
return calculateIsWayPoint()
}
}
//main logic
var train = new Train()
var doneWaiting = false
var doneWaitingTimeout = undefined
var gameLoop = setInterval(1000,function(){
...
if(train.isOnWaypoint() && !doneWaiting){
if(doneWaitingTimeout == undefined){
setTimeOut(5000,function(){
doneWaiting = true
doneWaitingTimeout = undefined
})
}
}
...
})
Here's the solution I finally came up with:
function drawTrackTimeout() {
if(gData != null && gIndex < gData.length) {
var trains = [];
trains[0] = gData[gIndex]['train'];
removeTrain(trains);
drawTrack(gData[gIndex]['y1'], gData[gIndex]['x1'], gData[gIndex]['y2'], gData[gIndex]['x2'], '#FF0', trains);
statusFinalDest = gData[gIndex]['status_final_dest'];
if(statusFinalDest == 'ARRIVED') {
unloadCargo();
} else if (gData[gIndex]['code'] == 'MOVE_TRAIN_AUTO' || gData[gIndex]['code'] == 'TURN_END') {
//moveTrainAuto();
} else {
// handle error
}
gIndex++;
} else {
clearInterval(gIntid);
gIntid = null;
gData = null;
gIndex = 0;
}
}
function myEventMoveTrainManual(evt, performErrorCheck) {
//debugger;
if(mutexMoveTrainManual == 'CONTINUE') {
var ajax = new Ajax();
var param = {};
if(evt) {
var cityId = evt.target.getParentNode().getId();
var param = { "city_id": cityId };
}
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data) {
var actionPrompt = document.getElementById('action-prompt');
actionPrompt.setInnerXHTML('<span><div id="action-text">'+
'Train en route to final destination...</div></span>');
gData = data;
gIndex = 0;
gIntid = setInterval(function(){drawTrackTimeout()},1000);
}
ajax.post(baseURL + '/turn/move-train-final-dest', param);
}
}
A timer to fire an AJAX call if no key is pressed. If a key is pressed, then abort the last timer and add a new timer. That is what I want to do but failed to success. Here is my code:
var t;
input.onkeyup = function(){
$('.confirmText').html('Checking...');
var timeStampObj = new Date()
var timeStamp = timeStampObj.getTime();
var oldTimeStamp = $(this).attr('timeStamp');//I store a timeStamp in the element
if(timeStamp < 500 + oldTimeStamp){
$(this).attr('timeStamp', timeStamp);
clearTimeout(t);
}
t = setTimeout(function(){
$.ajax({
url: 'serverScripts/settings/checkEmailAvailability.php',
data: 'email='+email,
success: function(text){
if(text == 'available'){
$('.confirmText').html('Available!');
}else{
$('.confirmText').html('Occupied!');
}
}
});
}, 500);//Half a second
$(this).attr('timeStamp', timeStamp);
}
It sounds like you're asking for a debouncer. The term comes from electronics. It's a way to prevent multiple events from firing within some time threshold. You can use the following function to create a new function that will only be called if a given amount of time has passed since the last event.
function debounce(callback, timeout, _this) {
var timer;
return function(e) {
var _that = this;
if (timer)
clearTimeout(timer);
timer = setTimeout(function() {
callback.call(_this || _that, e);
}, timeout);
}
}
// requires jQuery
$("div").click(debounce(function() {
console.log("tset");
}, 2000));
The callback given to debounce won't execute as long as click events keep firing.
The excellent Underscore.js library includes an equivalent function and there are at least a couple jQuery plugins:
http://code.google.com/p/jquery-debounce/
http://benalman.com/code/projects/jquery-dotimeout/examples/debouncing/
Where do you define the email variable in your JavaScript?
You need to define email somewhere and then check to see if your script works.
var email = $(this).value; // Pseudo-code - are you using jQuery?