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

我想在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!

当前回答

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

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>

其他回答

var i=0;
const waitFor = (ms) => 
{ 
  new Promise((r) => 
  {
   setTimeout(function () {
   console.log('timeout completed: ',ms,' : ',i); 
     i++;
     if(i==data.length){
      console.log('Done')  
    }
  }, ms); 
 })
}
var data=[1000, 200, 500];
data.forEach((num) => {
  waitFor(num)
})

在这个帖子中有许多解决方案和方法来实现这一点!

但是,如果你需要用map和async/await来做这个,那么这里就是

// Execution Starts
console.log("start")

// The Map will return promises
// the Execution will not go forward until all the promises are resolved.
await Promise.all(
    [1, 2, 3].map( async (item) => {
        await asyncFunction(item)
    })
)

// Will only run after all the items have resolved the asynchronous function. 
console.log("End")

输出将如下所示!可能根据异步函数而有所不同。

start
2
3
1
end

注意:如果你在map中使用await,它总是会返回promises数组。

希望这将解决你的问题,我通常与此工作时,我需要执行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();
}

在ES2018中,你可以使用异步迭代器:

const asyncFunction = a => fetch(a);
const itemDone = a => console.log(a);

async function example() {
  const arrayOfFetchPromises = [1, 2, 3].map(asyncFunction);

  for await (const item of arrayOfFetchPromises) {
    itemDone(item);
  }

  console.log('All done');
}

你不应该需要一个回调来迭代一个列表。只需在循环之后添加end()调用。

posts.forEach(function(v, i){
   res.write(v + ". Index " + i);
});
res.end();