(JavaScript)同步forEach循环里面的callback

我正在做一些forEach循环内的计算,如下所示:

 array.forEach(function(element){ Object.keys(element).forEach(function(key){ /* some complex computations with asynchronous callbacks */ }); }); someFunctionHere(); 

在执行someFunctionHere( )函数之前,Loop是否有办法完成? 或者在程序继续执行someFunctionHere( )之前知道Loop是否完成的任何方法…

我可能会错过一些论坛,但是我发现的那些论坛并没有帮助我实现我想要实现的目标,而且我在NodeJS中这样做,我也问是否有现成的库可以实现这个目的。

我忘了添加这个,或者这应该是另一个问题?

有没有一种方法同步进行迭代,只有在当前迭代完成后才会进行下一次迭代? (非常遗憾)

谢谢你的帮助…

       

网上收集的解决方案 "(JavaScript)同步forEach循环里面的callback"

看看async.js,尤其是它的控制stream程语句,比如whilstuntil

使用async.js你可以得到你想要的。

在你的实际情况下,你想要的是each函数(以前被称为forEach ), eachSeries函数不是并行地运行单个迭代,而是以串行方式(详见eachSeries的文档 )。

举个例子:

 async.eachSeries([ 2, 3, 5, 7, 11 ], function (prime, callback) { console.log(prime); callback(); // Alternatively: callback(new Error()); }, function (err) { if (err) { throw err; } console.log('Well done :-)!'); }); 

这将迭代素数的数组,然后按照正确的顺序依次打印出来,最后打印出来Well done :-)!

你可以将你的callback封装在倒计时中:

 var len = array.length; function countdownWrapper(callback, callbackArgs) { callback(callbackArgs); if (--len == 0) { someFunctionHere(); } } array.forEach(function(element){ Object.keys(element).forEach(function(key){ var wrappedCallback = countdownWrapper.bind(callback); /* some complex computations with asynchronous WRAPPED callbacks */ }); }); 

如果callbackArgs函数的参数个数不同,则可以对arguments而不是使用显式的callbackArgs参数。

编辑你的编辑澄清,你想在前面的计算完成它的callback之后开始每个复杂的计算。 这也可以通过closures容易地安排:

 function complexOp(key, callback) { /* . . . */ } function originalCallback(...) { /* . . . */ } function doSomethingElse() { /* . . . */ } var iteratorCallback = (function (body, callback, completion) { var i = 0, len = array.length; return function iterator() { callback.apply(null, arguments); if (++i < len) { body(array[i], iterator); } else { completion(); } }; }(complexOp, originalCallback, doSomethingElse)); // kick everything off: complexOp(array[0], iteratorCallback); 

高性能解决scheme:

可能会出现这种情况,您可能想要/允许asynchronous/并行处理数组,但希望在forEach的所有成员都被处理后调用该函数。 例:

 var async = require('async'); async.forEach(array,function(elementOfArray, callback){ //process each element of array in parallel // .. // .. // .. callback(); //notify that this iteration is complete }, function(err){ if(err){throw err;} console.log("processing all elements completed"); }); 

因此,这样就可以执行非阻塞的CPU密集型操作。

注:当您使用eachSeries巨大的数组时,太多的迭代callback可能会溢出堆栈。

在这里阅读: https : //github.com/caolan/async#control-flow

对于支持Promise(或使用polyfill)/ nodejs的浏览器,我已经实现了我自己的同步版forEach与callback,所以我只是在这里分享…

callback必须返回一个承诺..

 function forEachSync(array, callback) { let lastIndex = array.length - 1; let startIndex = 0; return new Promise((resolve, reject) => { // Finish all let functionToIterateWith = (currIndex) => { if (currIndex > lastIndex) { return resolve(); } else { callback(array[currIndex]).then(() => { functionToIterateWith(currIndex + 1); }).catch(err => reject(err)); } } functionToIterateWith(startIndex); }); }