我想为每个项目以相同的顺序执行一系列的事情并收集信息,然后在最后发送统计信息。
这是示例代码:
let listOfItems = [];
assignedItems.forEach(async (item) => {
let id = item.myID;
totalItemCount += await itemRepository.getItemCount(id);
let itemDetail = await itemRepository.getDetails(id);
listOfItems.push(item.name);
}, this);
console.log(listOfItems.length); // 0 ??
VS
let listOfItems = [];
for (let i = 0; i < assignedItems.length; i++) {
let id = assignedItems[i].myID;
totalItemCount += await itemRepository.getItemCount(id);
let itemDetail = await itemRepository.getDetails(id);
listOfItems.push(itemDetail.name);
}
console.log(listOfItems.length); // 5 as expected
使用foreach输出:0(因为foreach稍后执行) 输出使用for:5如预期的那样(因为在写入代码执行时执行)
主要问题是:foreach是在我的console.logs之后执行的,这些日志是在foreach之后编写的,因为我想首先收集项目的所有细节,然后发送我收集的数据。
到底是怎么回事?我如何使用foreach解决问题?
答案 0 :(得分:4)
.forEach()
无法按照您希望的方式使用await
。如果要序列化事物,只需使用for
循环await
。
如果您在使用.forEach()
时遇到问题,请解释该问题,以便我们帮助解决该问题。
.forEach()
是同步的,不会await
任何内容,也无法更改它。如果您希望循环的每次迭代都为await
您的承诺,则必须以不同的方式循环。 for
循环将在ES6中为您执行此操作(这是ES6的明确设计功能),或者您可以自定义您自己的await
手动循环代码,但.forEach()
不会执行它
到底是怎么回事?
.forEach()
是同步的。它没有await
你的承诺。这就是它的设计方式。
如何使用foreach解决问题?
你没有。如果要在继续之前等待循环的每次迭代,请使用常规for
循环。这是ES6的一项功能,包含常规for
循环,而不是.forEach()
。
仅供参考,如果您想要一个等待承诺的.forEach()
类似功能,您可以使用Bluebird promise library并使用Promise.mapSeries()
或Promise.each()
之类的内容。这些函数都寻找从它们的回调返回的promise,并且在这些promise被解析之前不执行下一次迭代。但是,array.forEach()
没有内置该功能。
还有使用.reduce()
的设计模式,并承诺通过调用串行异步操作的数组进行排序。您可以在这些答案中看到该模式的示例:
how to write to new files sequentially
Can Promise load multi urls in order?
iterating over promises node js
how to make synchronous http calls using promises in node.js
答案 1 :(得分:1)
请阅读这篇文章,希望你能在这里找到答案。 Here is the link