【发布时间】:2020-09-24 23:08:32
【问题描述】:
这是我目前的理解:
for 循环中的 async/await 应该暂停执行,直到 promise 解决,这意味着循环的下一次迭代在该行完成之前不会发生。
考虑以下数组:
const data = [];
for (let i = 0; i <= 100000; i++) {
data.push(i);
}
方法一:在for循环中等待Promise
async function method1() {
const startTime = new Date();
console.log('start:', startTime);
for (const item in data) {
await new Promise(resolve => {
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
});
}
const endTime = new Date();
console.log('finish:', endTime);
console.log('total time:', endTime-startTime);
}
因为它需要顺序执行 Promise 才能继续循环,所以我认为使用 Promise.all 将是一种性能增强,可以在更大程度上利用异步处理:
方法 2:Promise.all 跟随 for 循环
async function method2() {
const promises = [];
const startTime = new Date();
console.log('start:', startTime);
for (const item in data) {
const promise = new Promise(resolve => {
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
});
promises.push(promise);
}
await Promise.all(promises);
const endTime = new Date();
console.log('finish:', endTime);
console.log('total time:', endTime-startTime);
}
我的推理:当每个先前创建的 Promise 尝试解决时,循环将继续发出新的 Promise。所以在我看来,方法 1 = 阻塞......而方法 2 = 更少阻塞。
当我在 repl.it 上运行它们时,我发现方法 1 实际上更快,几乎快了 2 倍。有人可以解释为什么会这样吗?不应该反过来吗?
【问题讨论】:
-
这两种方法在概念上的区别在于,一种并行运行异步操作,另一种串行运行它们。使用虚假的异步操作,您看不到这种差异的真正效果。使用真正的异步操作,效果会很明显,并且并行运行会有更快的端到端时间。如果每个异步操作都需要
200ms来解析,那么方法 1 将在~n * 200ms中解析,而方法 2 将在~200ms中解析,其中 n 是您运行的异步操作的数量。
标签: javascript node.js asynchronous promise async-await