(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中这样做,我也问是否有现成的库可以实现这个目的。
我忘了添加这个,或者这应该是另一个问题?
有没有一种方法同步进行迭代,只有在当前迭代完成后才会进行下一次迭代? (非常遗憾)
谢谢你的帮助…
看看async.js,尤其是它的控制stream程语句,比如whilst
和until
。
使用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); }); }
- 悬挂callback:在每个callback已经返回之前返回响应
- response.setHeader和response.writeHead之间的区别?
- Microsoft Bot Framework请求中的MissingProperty错误
- 当密码包含数字时,bcrypt比较返回false
- JSON stringify将0转换为null
- GraphQL参数错误:参数types必须是inputtypes,但得到:function GraphQLObjectType(config){
- mongoose如何“删除”不存在的文件?
- IntelliJ使用自定义模块path时,“无法find声明去”
- 在MEAN堆栈应用程序中上传逻辑的适当位置是什么?