共计 1067 个字符,预计需要花费 3 分钟才能阅读完成。
async/await
应用起来十分棒,然而在 Array.forEach()
中却存在陷阱。
问题形容
例如说上面的代码:
const waitFor = (ms) => new Promise(r => setTimeout(r, ms));
[1, 2, 3].forEach(async (num) => {await waitFor(1000);
console.log(num);
});
console.log('Done');
在控制台执行下面代码后果如下(node.js 版本≥ 13.0.0):
$ node forEach.js
$ Done
$ 1
$ 2
$ 3
问题剖析
console.log(num)
的后果在最初才输入,并且是同时输入。
咱们创立一个 forEach()
办法了解下到底产生了什么事:
Array.prototype.forEach = function (callback) {
// 这里迭代咱们的数组
for (let index = 0; index < this.length; index++) {
// 每次迭代执行 callback 办法,传入对应参数
callback(this[index], index, this);
}
};
forEach()
的 polyfill 实现能够参考:MDN-Array.prototype.forEach()
能够看到,callback
并没有在 async/await
中执行,所以 Promise
的后果在最初才打印。
解决问题
咱们能够用本人写的 asyncForEach
办法代替forEach
:
asyncForEach([1, 2, 3], async (num) => {await waitFor(50);
console.log(num);
})
console.log('Done');
执行下面的代码,能够看到上面的后果:
$ node forEach.js
$ Done
$ 1
$ 2
$ 3
后果如同没什么区别,不过 console.log(num)
曾经在 async/await
中执行了,咱们也能够看到 setTimeout
的成果。
然而还不够现实,实际上 asyncForEach
返回的是一个 Promise
,因为它包裹在一个async
函数中,咱们能够期待它执行实现后再打印出最初的Done
:
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
正文完