正如标题所示。我怎么做呢?

我想在foreach循环遍历每个元素并完成一些异步处理后调用whenAllDone()。

[1, 2, 3].forEach(
  function(item, index, array, done) {
     asyncFunction(item, function itemDone() {
       console.log(item + " done");
       done();
     });
  }, function allDone() {
     console.log("All done");
     whenAllDone();
  }
);

有可能让它这样工作吗?当forEach的第二个参数是一个回调函数,当它经过所有迭代时运行?

预期的输出:

3 done
1 done
2 done
All done!

当前回答

希望这将解决你的问题,我通常与此工作时,我需要执行forEach与异步任务。

foo = [a,b,c,d];
waiting = foo.length;
foo.forEach(function(entry){
      doAsynchronousFunction(entry,finish) //call finish after each entry
}
function finish(){
      waiting--;
      if (waiting==0) {
          //do your Job intended to be done after forEach is completed
      } 
}

function doAsynchronousFunction(entry,callback){
       //asynchronousjob with entry
       callback();
}

其他回答

这是Node.js的异步解决方案。

使用异步NPM包。

(JavaScript)同步forEach循环内部回调

如果遇到异步函数,并且希望确保在执行代码之前完成它的任务,我们总是可以使用回调功能。

例如:

var ctr = 0;
posts.forEach(function(element, index, array){
    asynchronous(function(data){
         ctr++; 
         if (ctr === array.length) {
             functionAfterForEach();
         }
    })
});

注:functionAfterForEach是foreach任务完成后执行的函数。异步是在foreach内部执行的异步函数。

奇怪的是,异步情况下有多少错误的答案! 可以简单地表明,检查索引没有提供预期的行为:

// INCORRECT
var list = [4000, 2000];
list.forEach(function(l, index) {
    console.log(l + ' started ...');
    setTimeout(function() {
        console.log(index + ': ' + l);
    }, l);
});

输出:

4000 started
2000 started
1: 2000
0: 4000

如果我们检查index === array。长度- 1,回调将在第一次迭代完成时被调用,而第一个元素仍然悬而未决!

要在不使用async等外部库的情况下解决这个问题,我认为最好的方法是保存列表的长度,并在每次迭代后递减。因为只有一个线程,我们确定没有竞争条件的机会。

var list = [4000, 2000];
var counter = list.length;
list.forEach(function(l, index) {
    console.log(l + ' started ...');
    setTimeout(function() {
        console.log(index + ': ' + l);
        counter -= 1;
        if ( counter === 0)
            // call your callback here
    }, l);
});

我没有承诺的解决方案(这可以确保每个动作在下一个动作开始之前结束):

Array.prototype.forEachAsync = function (callback, end) { var self = this; function task(index) { var x = self[index]; if (index >= self.length) { end() } else { callback(self[index], index, self, function () { task(index + 1); }); } } task(0); }; var i = 0; var myArray = Array.apply(null, Array(10)).map(function(item) { return i++; }); console.log(JSON.stringify(myArray)); myArray.forEachAsync(function(item, index, arr, next){ setTimeout(function(){ $(".toto").append("<div>item index " + item + " done</div>"); console.log("action " + item + " done"); next(); }, 300); }, function(){ $(".toto").append("<div>ALL ACTIONS ARE DONE</div>"); console.log("ALL ACTIONS ARE DONE"); }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="toto"> </div>

我尝试简单的方法来解决它,分享给你:

let counter = 0;
            arr.forEach(async (item, index) => {
                await request.query(item, (err, recordset) => {
                    if (err) console.log(err);

                    //do Somthings

                    counter++;
                    if(counter == tableCmd.length){
                        sql.close();
                        callback();
                    }
                });

request是mssql库在Node js中的函数。这可以取代你想要的每个函数或代码。 古德勒克