How to call a function after all setTimeout functions is done - javascript

How to call the second function after the all previous functions is done.
function first() {
// code here
setTimeout( function() {
// code here
}, 1000);
// code here
setTimeout( function() {
// code here
}, 3000);
// code here
setTimeout( function() {
// code here
}, 3800);
}
function second() {
// code here
}
first();
first();
second();
first();
second();
It seems all functions executed in the same time.
Thanks a lot.

If you need to call a specific function after the last timeout, I think this will point you in the right direction. Of course, it can be written better, with reusable "class" etc.
function myTimeout(f,t) {
var p = new Promise(resolve=>{
setTimeout(()=>{
resolve(f.apply(this,[]));
}, t);
});
//return p.promise();
return p;
}
function first() {
var numberOfTimeouts = 3
// code here
myTimeout(()=>{
// code here
console.log('a')
}, 1000).then(()=>{
numberOfTimeouts--;
if (!numberOfTimeouts) second()
});
// code here
myTimeout( function() {
console.log('b')
}, 3000).then(()=>{
numberOfTimeouts--;
if (!numberOfTimeouts) second()
});
// code here
myTimeout( function() {
console.log('c')
}, 3800).then(()=>{
numberOfTimeouts--;
if (!numberOfTimeouts) second()
});
}
function second() {
console.log('d')
}
first();

Related

How to call a different function after completion of one function?

I have written long code, trying to replicate the situation in simple form by this simple code.
What I want to do is after function A() completion, call function B().
I am trying with callback function but in this case, B fired early.
Please suggest how can I write this callback or any other approach?
function A(callback){
a()
function a() {
setTimeout(aa,1000)
function aa(){
console.log("in aa")
}
}
b()
function b() {
setTimeout(bb,100)
function bb(){
console.log("in bb")
}
}
c()
function c(){
setTimeout(cc,50)
function cc(){
console.log("in cc")
}
}
callback();
}
function B() {
console.log("in B");
}
A(B)
output
in B
in cc
in bb
in aa
If you want your callback to run after a timeout has finished, then you have to call it when the timeout has finished.
And that means it needs to be at the end of the function you pass to setTimeout.
With your current code, you are setting the countdown on the timeout going and then immediately calling the callback.
function one(callback) {
console.log(1);
function two() {
console.log(2);
callback();
}
setTimeout(two, 250);
}
function three() {
console.log(3);
}
one(three);
Essentially, what's happening here (as you requested) is that you want B to run after A is completed.
There is no need to use "B" as a callback, with async/await.
B will wait till A is completed before it's called.
const b = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{resolve("B done")}, 1000);
});
}
const c = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{resolve("C done")}, 500);
});
}
const A = async () => {
const bres = await b();
console.log(bres);
const cres = await c();
console.log(cres);
};
const B = async () => {
console.log("done");
}
const app = async() => {
await A();
await B();
};
app();

Use async series and parallel with exported function in node.js

I'm trying to get my code to run using the async module. However, when the async.series runs, it only executes the third() function then stops. I understand that the first argument of async.series takes an array of tasks that requires a callback. However, I'm unsure as to how I'm supposed to do a callback on a function that I've exported from another file as in the functions first() and second(). Any help?
process.js:
var process = require('child_process');
function executeProcess() {
process.exec(...);
}
exports.Process = function() {
executeProcess();
}
app.js
var process = require('./process.js');
function first() {
process.Process();
}
function second() {
process.Process();
}
function third() {
console.log('third');
}
function parallel() {
async.parallel([first, second], function() {
console.log('first and second in parallel');
});
}
async.series([third, parallel], function() {
console.log('third then parallel');
});
You should use callback functions. I think your process.js is ok so I have not changed it. But I made some minor changes in the app.js. Just added there callback functions:
var process = require('./process.js');
var async = require("async");
function first(callback) {
console.log('FIRST');
process.Process();
callback();
}
function second(callback) {
console.log('SECOND');
process.Process();
callback();
}
function third(callback) {
console.log('third');
callback();
}
function parallel() {
async.parallel([first, second], function(callback) {
console.log('first and second in parallel');
});
}
async.series([third, parallel], function() {
console.log('third then parallel');
});
This should work. Here is an very good blogpost about async library:
Node.js async in practice: When to use what?

code under jquery done() executes before when()

Why does the code under the done() statement execute before the other 3 function which are called under when()? It goes immediately. I thought when was used to queue up functions and done was used to execute something when the when code was, well, done...
$(document).on('click', '.ajax', function() {
$.when(func1('<p>first</p>'), func2('<p>second</p>'), func3('<p>third</p>')).done(function() {
$('body').append('all done');
});
});
function func1(first) {
var t = setTimeout(function() {
$('body').append(first);
}, 800);
return "success";
}
function func2(second) {
var t = setTimeout(function() {
$('body').append(second);
}, 2700);
return "success";
}
function func3(third) {
var t = setTimeout(function() {
$('body').append(third);
}, 200);
return "success";
}​
http://jsfiddle.net/loren_hibbard/NhAFN/
You need to use $.Deferred() and return promise.
function func1(first) {
var dfd = $.Deferred();
var t = setTimeout(function() {
$('body').append(first);
dfd.resolve();
}, 800);
return dfd.promise();
}
http://jsfiddle.net/NhAFN/2/

Custom solution to implement callback function

Is it possible to wrap functions like setTimeout and then fire callback. Like in jQuery $(selector).on('action', callback).
var obj = {
mth1: function (callback) {
//----need to wrap to something
setTimeout(function () { console.log("1"); }, 1000);
console.log('2');
//----
// callback;
}
};
function callback() {
console.log('3');
};
(function () { obj.mth1(callback); }) ();
What I need:
2
1
3
Simply add it at the end of your function inside the setTimout
// *snip*
setTimeout(function () {
console.log("1");
callback();
}, 1000);
// *snip*
Not sure what you're asking for. Just make sure it is a function and call it:
mth1: function (callback) {
//----need to wrap to something
setTimeout(function () {
console.log("1");
// be sure it is a function
if (callback&& getType.toString.call(callback) == '[object Function]';) {
// call it
callback();
}
}, 1000);
console.log('2');
}

Chaining ajax requests with jQuery's deferred

I have a web app which must call the server multiple times. So far, I had a long nested callback chain; but I would like to use jQuery's when,then etc. functionality. However, I can't seem to get stuff running again after using a then.
$
.when ($.get('pages/run-tool.html'))
.then (function (args)
{
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.then ($.get('pages/test.html'))
.done (function(args)
{
// This prints the same as the last call
alert (args);
});
What am I doing wrong? I guess its some scoping issue, as I can see the second get call being executed. Using two different args variables does not help as the argument passed to the done function is still the first get request.
As an update:
With modern jquery (1.8+) you don't need the preliminary when because get returns a Deferred Promise.
Also, pipe is deprecated. Use then instead. Just be sure to return the result of the new get which becomes the Promise attached to by subsequent then/*done*/fail calls.
So:
$.get('pages/run-tool.html')
.then (function (args) { // this will run if the above .get succeeds
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.then (function() { // this will run after the above then-handler (assuming it ran)
return $.get('pages/test.html'); // the return value creates a new Deferred object
})
.done (function(args) { // this will run after the second .get succeeds (assuming it ran)
alert (args);
});
All three callbacks (the two with then and the one with done) are applied to the same request – the original when call. This is because then returns the same Deferred object, rather than a new one, so that you can add multiple event handlers.
You need to use pipe instead.
$
.when ($.get('pages/run-tool.html'))
.then (function (args)
{
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.pipe (function() {
return $.get('pages/test.html'); // the return value creates a new Deferred object
})
.done (function(args)
{
alert (args);
});
Here is an wonderfully simple and highly effective AJAX chaining / queue plugin. It will execute you ajax methods in sequence one after each other.
It works by accepting an array of methods and then executing them in sequence. It wont execute the next method whilst waiting for a response.
//--- THIS PART IS YOUR CODE -----------------------
$(document).ready(function () {
var AjaxQ = [];
AjaxQ[0] = function () { AjaxMethod1(); }
AjaxQ[1] = function () { AjaxMethod2(); }
AjaxQ[3] = function () { AjaxMethod3(); }
//Execute methods in sequence
$(document).sc_ExecuteAjaxQ({ fx: AjaxQ });
});
//--- THIS PART IS THE AJAX PLUGIN -------------------
$.fn.sc_ExecuteAjaxQ = function (options) {
//? Executes a series of AJAX methods in dequence
var options = $.extend({
fx: [] //function1 () { }, function2 () { }, function3 () { }
}, options);
if (options.fx.length > 0) {
var i = 0;
$(this).unbind('ajaxComplete');
$(this).ajaxComplete(function () {
i++;
if (i < options.fx.length && (typeof options.fx[i] == "function")) { options.fx[i](); }
else { $(this).unbind('ajaxComplete'); }
});
//Execute first item in queue
if (typeof options.fx[i] == "function") { options.fx[i](); }
else { $(this).unbind('ajaxComplete'); }
}
}
The answer cdr gave, which has the highest vote at the moment, is not right.
When you have functions a, b, c each returns a $.Deferred() object, and chains the functions like the following:
a().then(b).then(c)
Both b and c will run once the promise returned from a is resolved. Since both then() functions are tied to the promise of a, this works similiar to other Jquery chaining such as:
$('#id').html("<div>hello</div>").css({display:"block"})
where both html() and css() function are called on the object returned from $('#id');
So to make a, b, c run after the promise returned from the previous function is resolved, you need to do this:
a().then(function(){
b().then(c)
});
Here the call of function c is tied to the promise returned from function b.
You can test this using the following code:
function a() {
var promise = $.Deferred();
setTimeout(function() {
promise.resolve();
console.log("a");
}, 1000);
return promise;
}
function b() {
console.log("running b");
var promise = $.Deferred();
setTimeout(function () {
promise.resolve();
console.log("b");
}, 500);
return promise;
}
function c() {
console.log("running c");
var promise = $.Deferred();
setTimeout(function () {
promise.resolve();
console.log("c");
}, 1500);
return promise;
}
a().then(b).then(c);
a().then(function(){
b().then(c)
});
Change the promise in function b() from resolve() to reject() and you will see the difference.
<script type="text/javascript">
var promise1 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("1");
def.resolve();
}, 3000);
}).promise();
};
var promise2 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("2");
def.resolve();
}, 2000);
}).promise();
};
var promise3 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("3");
def.resolve();
}, 1000);
}).promise();
};
var firstCall = function () {
console.log("firstCall");
$.when(promise1())
.then(function () { secondCall(); });
};
var secondCall = function () {
console.log("secondCall")
$.when(promise2()).then(function () { thirdCall(); });
};
var thirdCall = function () {
console.log("thirdCall")
$.when(promise3()).then(function () { console.log("done"); });
};
$(document).ready(function () {
firstCall();
});
</script>
I thought I would leave this little exercise here for anyone who may find it useful, we build an array of requests and when they are completed, we can fire a callback function:
var urls = [{
url: 'url1',
data: 'foo'
}, {
url: 'url2',
data: 'foo'
}, {
url: 'url3',
data: 'foo'
}, {
url: 'url4',
data: 'foo'
}];
var requests = [];
var callback = function (result) {
console.log('done!');
};
var ajaxFunction = function () {
for (var request, i = -1; request = urls[++i];) {
requests.push($.ajax({
url: request.url,
success: function (response) {
console.log('success', response);
}
}));
}
};
// using $.when.apply() we can execute a function when all the requests
// in the array have completed
$.when.apply(new ajaxFunction(), requests).done(function (result) {
callback(result)
});
My way is to apply callback function:
A(function(){
B(function(){
C()})});
where A, B can be written as
function A(callback)
$.ajax{
...
success: function(result){
...
if (callback) callback();
}
}

Categories