等待.forEach()完成的最佳方式

Jaa*_*and 23 javascript angularjs

有时我需要等待.forEach()方法完成,主要是在'loader'函数上.这就是我这样做的方式:

$q.when(array.forEach(function(item){ 
    //iterate on something 
})).then(function(){ 
    //continue with processing 
});
Run Code Online (Sandbox Code Playgroud)

我不禁觉得这不是等待.forEach()完成的最好方法.做这个的最好方式是什么?

小智 38

var foo = [1,2,3,4,5,6,7,8,9,10];
Run Code Online (Sandbox Code Playgroud)

如果你实际上是在循环中做异步的东西,你可以把它包装在一个承诺中......

var bar = new Promise((resolve, reject) => {
    foo.forEach((value, index, array) => {
        console.log(value);
        if (index === array.length -1) resolve();
    });
});

bar.then(() => {
    console.log('All done!');
});
Run Code Online (Sandbox Code Playgroud)

  • 这不能正常工作!正如@akrz所说,只有当具有最高索引的承诺也需要最长的时间时,这才有效。情况可能*永远不会*是这样。 (5认同)
  • 例如,如果具有键 1 的元素比具有键 2 的元素需要更长的处理时间,这将错误地解析承诺。 (4认同)

Aqe*_*eel 14

使用for of而不是forEach. 像这样:

for (const item of array) {
  //do something
}
console.log("finished");
Run Code Online (Sandbox Code Playgroud)

finished完成循环后将记录“ ”。


Dou*_*ank 12

使用ES6进行这项工作的最快方法就是使用for..of循环。

const myAsyncLoopFunction = async (array) {
  const allAsyncResults = []

  for (const item of array) {
    const asnycResult = await asyncFunction(item)
    allAsyncResults.push(asyncResult)
  }

  return allAsyncResults
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用以下方法并行遍历所有这些异步请求Promise.all()

const myAsyncLoopFunction = async (array) {
  const promises = array.map(asyncFunction)
  await Promise.all(promises)
  console.log(`All async tasks complete!`)
}
Run Code Online (Sandbox Code Playgroud)

  • Promise.all() 版本需要是 `const myAsyncLoopF​​unction = async (array) => {` 或 `const myAsyncLoopF​​unction = async function (array) {` 才能使其成为一个函数! (3认同)
  • 如果有一个解释就会使它有用。功能是哪一部分?如何将数组的每一项传递给外部函数? (2认同)

Ism*_*OUH 10

forEach 不是异步的,例如在这段代码中:

array.forEach(function(item){ 
    //iterate on something 
});
alert("Foreach DONE !");
Run Code Online (Sandbox Code Playgroud)

forEach完成后你会看到警报.

  • 如果循环内没有异步处理,这是可以的. (30认同)
  • 警报将在 foreach 完成之前触发。这不起作用。 (3认同)
  • 这是行不通的,forEach循环不能保证按顺序运行,因此当index === array.length检查通过时,不能保证所有项目都已被处理。我认为@PJ3 的答案是最简单且有效的。 (2认同)

小智 8

forEach() 不返回任何内容,因此更好的做法是map()+Promise.all()

var arr = [1, 2, 3, 4, 5, 6]

var doublify = (ele) => {
  return new Promise((res, rej) => {
    setTimeout(() => {
        res(ele * 2)
    }, Math.random() ); // Math.random returns a random number from 0~1
  })
}

var promises = arr.map(async (ele) => {
  // do some operation on ele
  // ex: var result = await some_async_function_that_return_a_promise(ele)
  // In the below I use doublify() to be such an async function

  var result = await doublify(ele)
  return new Promise((res, rej) => {res(result)})
})

Promise.all(promises)
.then((results) => {
  // do what you want on the results
  console.log(results)
})
Run Code Online (Sandbox Code Playgroud)

输出

  • 解决方案适用于 for-each 中的异步任务。非常感谢! (2认同)

PJ3*_*PJ3 5

如果您在循环中有一个异步任务并且您想等待。您可以使用for await

for await (const i of images) {
    let img = await uploadDoc(i);
};

let x = 10; //this executes after
Run Code Online (Sandbox Code Playgroud)