在asynchronous调用节点后做些事情

假设我有四个不同的asynchronous操作需要运行,并且它们都可以独立运行。 但是还有一个剩余的函数需要使用这些asynchronous调用收集的所有数据,所以只能在所有这些完成后才能完成。

一个简单的方法是使asynchronous调用相互调用,然后调用最终函数,如下所示:

myObj.async1(function () { myObj.async2(function () { myObj.async3(function () { myObj.async4(function () { ... finalFunction(); 

但是这样做是一个糟糕的方法,因为节点是围绕asynchronousfunction构build的。 相反,我们假设我们想要这样做:

 myObj.async1(async1Callback); myObj.async2(async2Callback); myObj.async3(async3Callback); myObj.async4(async4Callback); if( //Some logic here to determine when all four functions have completed finalFunction(); 

什么是确定这个逻辑的最好方法? 我认为每个函数都设置了一个布尔variables来表示它是否已经完成,然后有一个基于时间的发射器,它不断地检查所有四个variables是否设置为true,然后调用finalFunction,但是如果有的话可能会变得混乱所有这些变数都在附近。

任何想法是什么是最好的办法做到这一点?

我会利用这个async库,例如

 async.parallel([ myObj.async1, myObj.async2, myObj.async3, myObj.async4 ], function(err) { if (err) throw err; // Run final function now that all prerequisites are finished finalFunction(); }); 

这假定每个myObj.async* function都将callbackfunction作为其唯一参数,并且callbackfunction的第一个参数是一个err参数。 有关更多信息,请参阅async#parallel()的文档 。

作为@jabclab的推荐,看看asynchronous,因为它为你pipe理大部分的复杂性。 但是,如果您想要做这样的事情,您可以select以下几种方法。

从一个myObj开始,如下所示:

 var myObj = { async1: function async1(cb) { setTimeout(function() { console.log('async1'); cb(null, {name: 'async1'}); }, 1000)}, async2: function async2(cb) { setTimeout(function() { console.log('async2'); cb(null, {name: 'async2'}); }, 500)}, async3: function async3(cb) { setTimeout(function() { console.log('async3'); cb(null, {name: 'async3'}); }, 1001)}, async4: function async4(cb) { setTimeout(function() { console.log('async4'); cb(null, {name: 'async4'}); }, 200)} } 

这个版本是硬编码调用四个特定的function和callback时,结果是完整的。 结果按照完成顺序排列。 每个结果对象都包含函数的名称以及任何错误或成功结果。

 function doFourSpecificThings(callback) { var results = []; var storeResults = function(fnName, err, resp) { results.push( { fnName: fnName, err: err, resp: resp } ); if(results.length === 4 && callback) { callback(results); } } // Bind the callback to myObj and pass the name of the called function // as the first argument myObj.async1(storeResults.bind(myObj, 'async1')); myObj.async2(storeResults.bind(myObj, 'async2')); myObj.async3(storeResults.bind(myObj, 'async3')); myObj.async4(storeResults.bind(myObj, 'async4')); } doFourSpecificThings(function(results) { console.log(results); }); 

输出:

 async4 async2 async1 async3 Results: [ { fnName: 'async4', err: null, resp: { name: 'async4' } }, { fnName: 'async2', err: null, resp: { name: 'async2' } }, { fnName: 'async1', err: null, resp: { name: 'async1' } }, { fnName: 'async3', err: null, resp: { name: 'async3' } } ] 

这个版本更灵活一些。 这些任务以一个数组forms传递,结果以相同的顺序存储在结果数组中:

 function doABunchOfStuff(tasks, callback) { var results = []; var expected = tasks.length; var storeResults = function(idx, err, resp) { results[idx] = { err: err, resp: resp }; --expected; if((expected === 0) && callback) { callback(results); } } // Using bind here to pass the current index to the storeResults() // callback as the first parameter for(var i = 0; i < tasks.length; ++i) { tasks[i](storeResults.bind(tasks[i], i)); } } doABunchOfStuff([ myObj.async1.bind(myObj), myObj.async2.bind(myObj), myObj.async3.bind(myObj), myObj.async4.bind(myObj)], function(results) { console.log('\nResults:'); console.log(results); }); 

输出:

 async4 async2 async1 async3 Results: [ { err: null, resp: { name: 'async1' } }, { err: null, resp: { name: 'async2' } }, { err: null, resp: { name: 'async3' } }, { err: null, resp: { name: 'async4' } } ]