async/await
非常棒,但有一个地方很棘手:在forEach()
中
让我们试一下:
const waitFor = (ms) => new Promise(r => setTimeout(r, ms));[1, 2, 3].forEach(async (num) => {
await waitFor(50);
console.log(num);
});console.log('Done');
如果你使用 node.js(≥ 7.6.0)运行此代码,会发生以下情况:
$ node forEach.js
$ Done
怎么回事?
console.log(num)
没有显示在控制台中。
让我们重新创建 forEach()
以理解发生了什么:
Array.prototype.forEach = function (callback) {
// this represents our array
for (let index = 0; index < this.length; index++) {
// We call the callback for each entry
callback(this[index], index, this);
}
};
<em>forEach()</em>
的真正 polyfill 可在 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill 中找到。
正如你所看到的,callback
被调用了,但在进入数组的下一个条目之前,我们没有等待它完成。
我们可以通过创建自己的 asyncForEach()
方法来解决这个问题:
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
然后,我们可以更新我们的示例来使用我们的 asyncForEach
方法:
asyncForEach([1, 2, 3], async (num) => {
await waitFor(50);
console.log(num);
})console.log('Done');
通过在 node 中运行此代码,我们现在可以看到:
$ node forEach.js
$ Done
$ 1
$ 2
$ 3
我们离成功更近了!
实际上,我们的 asyncForEach
返回一个 Promise
(因为它被包装在一个 async
函数中),但我们在记录 'Done' 之前没有等待它完成。
让我们再次更新我们的示例,将执行包装在一个 async
方法中:
const start = async () => {
await asyncForEach([1, 2, 3], async (num) => {
await waitFor(50);
console.log(num);
});
console.log('Done');
}start();
让我们最后运行一次:
$ node forEach.js
$ 1
$ 2
$ 3
$ Done
🎉 现在我们有一种使用 forEach
和 async/await
的方法了 🎉
评论(0)