Is it possible to kill an asynchronous function call in node.js or do I have to call the function and then another one to kill the whole process after a specific amount of time?
Probably not, But check following code, you can get some idea to achieve the stuff.
var logrunningFunction = function(){
setTimeout(function(){
console.log("Delayed");
cb();
}, 5000);
};
var cb = function(){
console.log("long running function completed");
};
logrunningFunction(cb);
setTimeout(function(){
cb = function(){
console.log("Overwrite long running handler");
};
},1000);
Related
Well i have this function here that runs on intervals and what it does is, when it runs, it sets 2 settimeout.
Here's the problem, an asynchronous function that should be called after the 2nd time out is called before the 2nd timeout is even triggered. This is my code.
var runner = Interval.run(function() {
//-212965881
bot.sendMessage('-212965881', "Drop usernames now").then(function(){
ready = 1;
list = {};
console.log(ready);
setTimeout(function(){
return bot.sendMessage('-212965881',"Round has begun. Please start liking now. Leech check will begin in 1 minute");
}, 10000);
}).then(function(){
ready = 0;
setTimeout(function(){
return bot.sendMessage('-212965881',"Leech check has begun!");
}, 15000);
}).then(function(){
//This one fires before 15 seconds
let msg = {chat:{}};
msg.chat.id = '-212965881';
return bot.event('/check', msg);
}).catch(function(err){
console.log(err);
});
}, 20000);
Not sure why this happens. Perhaps im going about it the wrong way.
Can anyone throw some light on this? Thanks
This happens because the code inside your then handlers are creating un-returned asynchronous code, or basically "breaking out" of the Promise chain without notifying the Promise chain of the activities.
You need to wrap your setTimeout inside of a Promise constructor and then also make sure you wait for the interior bot.sendMessage invocations to finish by resolving them inside your new Promises
Change it to use Promise constructors, see Resolving a Promise
var runner = Interval.run(function() {
//-212965881
bot.sendMessage('-212965881', "Drop usernames now").then(function(){
ready = 1;
list = {};
console.log(ready);
return new Promise((resolve) {
setTimeout(function(){
resolve(bot.sendMessage('-212965881',"Round has begun. Please start liking now. Leech check will begin in 1 minute"))
}, 10000);
});
}).then(function(){
ready = 0;
return new Promise((resolve) {
setTimeout(function(){
resolve(bot.sendMessage('-212965881',"Leech check has begun!"))
}, 15000);
});
}).then(function(){
//This one fires before 15 seconds
let msg = {chat:{}};
msg.chat.id = '-212965881';
return bot.event('/check', msg);
}).catch(function(err){
console.log(err);
});
}, 20000);
because the asynchronous functions you were trying to invoke are returned few seconds later. The three .then you wrote works on the first Promise repeatly.
your can use co module or ES6 async/await to control multiple Promise.
So I have a node app that when it's started makes an object.
function my_object(){
}
my_object.prototype.say_lol = function() {
setTimeout(function(){
console.log('lol');
}, 1000);
};
var ping = new my_object();
ping.say_lol();
process.on( 'SIGINT', function() {
delete global.ping; // Please?
// pseudo code to go update something in the database or whatever
setTimeout(function(){
process.exit();
}, 4000);
});
When it ends I need to delete that object to prevent it from firing lol over and over while the timeout is pending. Is there any elegant way of doing this?
You need to capture the id of what setTimeOut returns and then clear it if you don't want to fire at a later point.
my_object.prototype.say_lol = function() {
return (setTimeout(function(){
console.log('lol');
}, 1000));
};
var ping = new my_object();
var timeOutId = ping.say_lol();
process.on( 'SIGINT', function() {
clearTimeout(timeOutId);
process.exit();
});
If the event is not fired yet, it will be cancelled. If its already fired, it fails silenty.
I don't know of a way to stop the callback from firing. My approach would be to keep track of ping's state in another variable and use an if statement wrapping whatever chunk of code fires the unwanted callbacks.
function my_object(){ };
var stillHere = true;
my_object.prototype.say_lol = function() {
setTimeout(function(){
if(stillHere){
console.log('lol');
}
}, 2000);
};
var ping = new my_object();
ping.say_lol();
process.on( 'SIGINT', function() {
delete global.ping; // Please?
stillHere = false;
setTimeout(function(){
process.exit();
}, 4000);
});
Although I understand it's not a true answer, but this solved my issue. I ran the node process in a cluster and killed off any children that I wanted to delete. This worked in my instance as the children were performing endless tasks and when I needed them to be stopped that was the only logical way I could abort them.
I want to repeat a function every 10s with setTimeout. My function is:
dateInLive = function() {
crono = function(){
setTimeout(function() {
$('.datePoste').each(function(){
$(this).load('in_live.php','in_live='+$(this).attr('id'))
});
crono();
}
,10000);
}
crono();
}
But, it's really random; sometimes it's repeating after 15s, sometimes after 3s, sometimes after 6s.
Recall crono() only when all the ajax requests are completed :
function crono(){
setTimeout(function() {
var arr = [];
$('.datePoste').each(function(){
var self = this;
xhr = $.get('in_live.php', {in_live : this.id}, function(data) {
$(self).html( $.parseHTML(data) );
});
arr.push(xhr);
});
$.when.apply($, arr).done(crono);
}, 10000);
}
You're using setTimeout to run a repeated event.
This is correct (others have recommended setInterval instead, but there are issues with this).
However you aren't setting the timeout on the subsequent calls -- you're just calling the crono() function directly, so after the initial timeout delay, it will then just start calling itself immediately over and over and over forever (until it exhausts the stack space).
What you need to do is call setTimeout() each time you call the function. Recode it something like this:
dateInLive = function() {
crono = function(){
$('.datePoste').each(function(){
$(this).load('in_live.php','in_live='+$(this).attr('id'))
});
setTimeout(crono,10000);
}
setTimeout(crono,10000);
}
In this situation, i would use deferred objects.
function crono(){
setTimeout(function() {
var defArr = [];
$('.datePoste').each(function(i,el){
var deferred = $.Deferred();
defArr.push(deferred.promise());
$(this).load('in_live.php','in_live='+$(this).attr('id'), function() {
deferred.resolve();
});
});
$.when.apply($,defArr).done(crono);
}, 10000);
}
Doing it this way will request all sections, then when all sections are received, wait 10 seconds and request them again, avoiding the request from piling up in a slow network situation.
you are doing something before creating the new timeout, which means there is bound to be "some" delay.
have a look at the setInterval() function.
You just have the crono() function in the wrong place.
dateInLive = function() {
crono = function(){
setTimeout(function() {
crono();
$('.datePoste').each(function(){
$(this).load('in_live.php','in_live='+$(this).attr('id'))
});
}
,10000);
}
}
I have an asynchronous QUnit test where the test should pass if the operation times out. (I'm testing that if you omit an optional errorCallback and do something that throws an error, basically nothing happens no matter how long you wait.)
How would I do that? If I use Qunit.config.testTimeout then the test will fail on timeout. I want to set a timeout and have the test succeed when the timeout is reached.
Why not just go with a setTimeout call making the test succeed?
e.g.:
expect(1);
stop();
doOperation(function () {
start();
ok(false, "should not have come back");
});
setTimeout(function () {
start();
ok(true);
}, timeoutValue);
This is how I do in these cases (roughly):
function timeout(assert,to,error){
var done = assert.async();
var a = setTimeout(function(){
assert.equal(to,undefined,error);
done();
},to);
return function(){
done();
clearTimeout(a);
};
}
then you can:
...
var done = timeout(assert,2000,"not joined");
r.join(function(data){
assert.ok(true,"join confirmed");
done();
})
You may agument timeout function to timeout(assert,to,toCB) and execute the toCB instead of my dummy assert.equal
This is a typical situation in node.js:
asyncFunction(arguments, callback);
When asynFunction completes, callback gets called. A problem I see with this pattern is that, if asyncFunction never completes (and asynFunction doesn't have a built-in time-out system) then callback will never be called. Worse, it seems that callback has no way of determining that asynFunction will never return.
I want to implement a "timeout" whereby if callback has not been called by asyncFunction within 1 second, then callback automatically gets called with the assumption that asynFunction has errored out. What is the standard way of doing this?
I'm not familiar with any libraries that do this, but it's not hard to wire up yourself.
// Setup the timeout handler
var timeoutProtect = setTimeout(function() {
// Clear the local timer variable, indicating the timeout has been triggered.
timeoutProtect = null;
// Execute the callback with an error argument.
callback({error:'async timed out'});
}, 5000);
// Call the async function
asyncFunction(arguments, function() {
// Proceed only if the timeout handler has not yet fired.
if (timeoutProtect) {
// Clear the scheduled timeout handler
clearTimeout(timeoutProtect);
// Run the real callback.
callback();
}
});
You probably need to come out with a solution of your own. Like
function callBackWithATimeout (callback, timeout) {
var run, timer;
run = function () {
if (timer) {
clearTimeout(timer);
timer = null;
callback.apply(this, arguments);
}
};
timer = setTimeout(run, timeout, "timeout");
return run;
}
and then
asyncFunction(arguments, callBackWithATimeout(callback, 2000));
You could do something like this:
function ensureExecution(func, timeout) {
var timer, run, called = false;
run = function() {
if(!called) {
clearTimeout(timer);
called = true;
func.apply(this, arguments);
}
};
timer = setTimeout(run, timeout);
return run;
}
Usage:
asyncFunction(arguments, ensureExecution(callback, 1000));
DEMO
But note the following:
The timeout is started immediately when you call ensureExecution, so you cannot cache that function reference.
The arguments passed to the callback will differ. For example asyncFunction might pass some arguments to callback upon success, but if the function is called by the timeout, no arguments will be passed. You have to keep that it mind. You could also provide default arguments with which the function should be called in this case:
function ensureExecution(func, timeout, args, this_obj) {
// ...
timer = setTimeout(function() {
run.apply(this_obj, args);
}, timeout);
//...
}
I ran into the same problem with a content script trying to open the port on the BG extension before the BG extension was ready. A work around was to wait for the BG extension to reply to a message and repeat this till successful. Here are the code snippets.
Content Script:
var nTimes = 10;
var bIsReady = false;
checkBGReady();
function checkBGReady() {
if (!bIsReady) {
chrome.runtime.sendMessage({msgText: "hello "+nTimes}, function(response) {
if (response && response.ack) {
console.log("have response:"+response.ack+" "+nTimes);
bIsReady = true;
// continue with initialization
bootStrap(sURL);
checkReady();
} else {
console.log("have no ack response %o",response);
}
});
}
nTimes -= 1;
if (nTimes > 0 && !bIsReady) {
setTimeout(checkBGReady,100);
}
}
BG Extension
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");
if (request.msgText) {
console.log("Have msg "+request.msgText);
sendResponse({ack: "have contact "+request.msgText});
}
});
In my case it usually took after the first 100ms delay.