javascript: execute a bunch of asynchronous method with one callback
I need to execute a bunch of asynchronous methods (client SQLite database), and call only one final c开发者_如何学Pythonallback.
Of course, the ugly way is:
execAll : function(callBack) {
asynch1(function() {
asynch2(function() {
...
asynchN(function() {
callBack();
})
})
});
}
But I know there are better ways to do it. Intuitively I would detect when all call back has been called with a counter to call the final callback.
I think this is a common design-pattern, so if someone could point me in the right direction...
Thanks in advance !
this is easy
var callback = (function(){
var finishedCalls = 0;
return function(){
if (++finishedCalls == 4){
//execute your action here
}
};
})();
Just pass this callback to all your methods, and once it has been called 4 times it will execute.
If you want to use factory for this then you can do the following
function createCallback(limit, fn){
var finishedCalls = 0;
return function(){
if (++finishedCalls == limit){
fn();
}
};
}
var callback = createCallback(4, function(){
alert("woot!");
});
async1(callback);
async2(callback);
async3(callback);
async4(callback);
I've written some async utilities you might find useful, allowing you to write your example as:
function(callback) {
async.series([
asynch1(),
asynch2(),
...
asynchN()
], callback);
}
Or, if you wanted to run them in parallel, as:
function(callback) {
async.parallel([
asynch1(),
asynch2(),
...
asynchN()
], callback);
}
There are loads of other useful functions like async map/reduce too:
http://caolanmcmahon.com/async.html
Hope that helps!
You should consider using Deferred pattern for asynchronous methods. You can get more information from the this StackOverflow question and answers:
What are the differences between Deferred, Promise and Future in JavaScript?
The marked answer from jnewman was good actually!
Hope this helps.
Promises can help manage this. There are two general scenarios - parallel and serial. Parallel can be accomplished using Promise.all(), serial is more complex - task B can only start when task A is done. Here's a bare-bones sample:
// returns a promise that resolves as the task is done
const wrap = (fn, delay) => new Promise(resolve => setTimeout(_ => resolve(fn()), delay));
const task = (fn, delay) => delay ? wrap(fn, delay) : Promise.resolve(fn());
// given a list of promises, execute them one by one.
const sequence = async l => l.reduce(async (a, b) => [].concat(await a, await b));
const tasks = [
task(_ => console.log("hello world")),
task(_ => console.log("hello future"), 1000)
];
sequence(tasks).then(_ => console.log("all done"));
You may need some ES6/7 translation to make this work in browsers or older node versions.
精彩评论