我在双forEach
循环中进行一些计算,如下所示:
array.forEach(function(element){
Object.keys(element).forEach(function(key){
/* some complex computations with asynchronous callbacks */
});
});
someFunctionHere();
在执行someFunctionHere( )
功能之前,Loop是否有办法先完成?或者在继续someFunctionHere( )
...
我可能会遗漏一些论坛,但是我找到的论坛并没有帮助我实现我想要实现的目标,而且我在NodeJS中这样做,我也在问是否有现有的库可以实现这一点。
我忘了添加它或者这是另一个问题吗?
有没有办法同步进行迭代,一旦当前迭代完成,它只会进入下一次迭代? (对不起)
感谢您的帮助......
答案 0 :(得分:44)
查看async.js,尤其是each
语句,例如whilst
until
和each
。
使用async.js可以得到你想要的东西。
在您的实际情况中,您想要的是forEach
函数(以前称为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 :-)!');
});
函数,它不会并行运行单个迭代,但是是连续的(详见control flow)。
举个例子:
Well done :-)!
这将遍历素数数组并以正确的顺序打印出来,一个接一个地打印出来,最后打印出{{1}}。
答案 1 :(得分:6)
您可以将回调包装在倒计时结束中:
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 */
});
});
如果回调的参数数量不同,您可以在arguments
上进行一些手术,而不是使用明确的callbackArgs
参数。
编辑您的编辑说明您希望在上一次计算完成回调后启动每个复杂计算。这也可以通过闭包轻松安排:
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);
答案 2 :(得分:2)
高性能解决方案:
可能存在这样的情况:您可能希望/允许异步/并行处理数组,但希望在处理完所有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 时,许多迭代回调可能会溢出堆栈。
答案 3 :(得分:2)
对于支持Promise(或使用polyfill)/ nodejs的浏览器,我已经使用回调实现了我自己的forEach同步版本,所以我只是在这里分享..
回调必须返回一个承诺..
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);
});
}
答案 4 :(得分:1)
dirp