javascript Javascript如何在for循环完成后执行代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25064094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript how to execute code after for loop completes
提问by Catfish
I'm trying to work through this js/async scenario and i'm trying to know how the rest of the js world handles this.
我正在尝试解决这个 js/async 场景,我想知道 js 世界的其他部分是如何处理这个的。
function doStuff(callback) {
cursor.each(function(err, blahblah) {
...doing stuff here takes some time
});
... Execute this code ONLY after the `cursor.each` loop is finished
callback();
EDIT
编辑
Here's a more concrete example updated using most of the suggestions below which still doesn't work.
这是一个更具体的示例,使用下面的大多数建议进行了更新,但仍然不起作用。
function doStuff(callback) {
MongoClient.connect(constants.mongoUrl, function(err, db) {
var collection = db.collection('cases2');
var cursor = collection.find();
var promises = []; // array for storing promises
cursor.each(function(err, item) {
console.log('inside each'); // NEVER GETS LOGGED UNLESS I COMMENT OUT THIS LINE: return Q.all(promises).then(callback(null, items));
var def = Q.defer(); // Create deferred object and store
promises.push(def.promise); // Its promise in the array
if(item == null) {
return def.resolve();
}
def.resolve(); // resolve the promise
});
console.log('items'); // ALWAYS GETS CALLED
console.log(items);
// IF I COMMENT THIS LINE OUT COMPLETELY,
// THE LOG STATEMENT INSIDE CURSOR.EACH ACTUALLY GETS LOGGED
return Q.all(promises).then(callback(null, items));
});
}
回答by dreamlab
without using promises or any other dependencies/libraries you can simply
不使用承诺或任何其他依赖项/库,您可以简单地
function doStuff(callback) {
add a counter
添加计数器
var cursor = new Array(); // init with some array data
var cursorTasks = cursor.length;
function cursorTaskComplete()
{
cursorTasks--;
if ( cursorTasks <= 0 ) {
// this gets get called after each task reported to be complete
callback();
}
}
for ( var i = 0; i < cursor.length; i++ ) {
...doing stuff here takes some time and does some async stuff
check after each async request
在每个异步请求之后检查
...when async operation is complete call
cursorTaskComplete()
}
}
回答by Alnitak
Without knowing the details of the async calls you're making within the cursor.each
loop, I shall assume that you have the ability to invoke a callback each time the functions invoked therein have completed their async task:
在不知道您在cursor.each
循环中进行的异步调用的详细信息的情况下,我假设您有能力在每次调用的函数完成异步任务时调用回调:
function doStuff() {
var promises = []; // array for storing promises
cursor.each(function(err, blahblah) {
var def = Q.defer(); // create deferred object and store
promises.push(def.promise); // its promise in the array
call_async_function(..., def.resolve); // resolve the promise in the async function's callback
});
// pass the array to Q.all, only when all are resolved will "callback" be called
return Q.all(promises);
}
and the usage then becomes:
然后用法变成:
doStuff().then(callback)
Note how the invocation of the callback now never touches the doStuff
function - that function now also returns a promise. You can now register multiple callbacks, failure callbacks, etc, all without modifying doStuff
. This is called "separation of concerns".
请注意回调的调用现在如何从不触及该doStuff
函数 - 该函数现在也返回一个承诺。您现在可以注册多个回调、失败回调等,而无需修改doStuff
. 这称为“关注点分离”。
[NB: all the above based on the Q promises library - https://github.com/kriskowal/q]
[注意:以上所有内容均基于 Q 承诺库 - https://github.com/kriskowal/q]
EDITfurther discussion and experimentation has determined that the .each
call is itself async, and gives no indication to the outside when the last row has been seen. I've created a Gistthat demonstrates a resolution to this problem.
编辑进一步的讨论和实验已经确定.each
调用本身是异步的,并且在看到最后一行时不会向外部发出任何指示。我创建了一个Gist来演示这个问题的解决方案。
回答by V31
if you want to do it with the async module, you can make use of the async forEachSeries function
如果你想用 async 模块来做,你可以使用 async forEachSeries 函数
Code snippet:
代码片段:
function doStuff(callback) {
async.forEachSeries(cursor, function(cursorSingleObj,callbackFromForEach){
//...do stuff which takes time
//this callback is to tell when everything gets over execute the next function
callbackFromForEach();
},function(){
//over here the execution of forEach gets over and then the main callback is called
callback();
});
}
回答by bhantol
In my mind an elegant/ideal solution would be to have something like
在我看来,一个优雅/理想的解决方案是拥有类似的东西
cursor.each(........).then( function() { ....your stuff});
But without that you can do this....UPDATED
但没有它,你可以做到这一点......更新
http://plnkr.co/edit/27l7t5VLszBIW9eFW4Ip?p=preview
http://plnkr.co/edit/27l7t5VLszBIW9eFW4Ip?p=preview
The gist of this is as shown below...notice....when
其要点如下所示......注意......当
var doStuff = function(callback) {
cursor.forEach(function(cursorStep) {
var deferred = $q.defer();
var promise = deferred.promise;
allMyAsyncPromises.push(promise);
cursorStep.execFn(cursorStep.stepMeta);
promise.resolve;
});
$q.when(allMyAsyncPromises).then(callback);
}
After hitting the start button wait for few seconds...the async tasks have been simulated to finish in 5 seconds so the status will update accordingly.
点击开始按钮后等待几秒钟......异步任务已被模拟为在 5 秒内完成,因此状态将相应更新。
Not having access to a real cursor object..I had to resort of fake cursor like and array.
无法访问真正的游标对象..我不得不求助于假游标和数组。