`for await...of`与同步可迭代对象中await Promise的区别及等价性疑问
for await...of 和普通for...of+await的差异 这两段代码不完全等价,for await...of的作用远不止省去一个变量,核心差异在于它们能处理的可迭代对象类型完全不同:
场景1:遍历普通可迭代对象(如Promise数组)
如果iterableWithPromises是普通同步可迭代对象(比如每个元素都是Promise的数组),两段代码的行为确实一致——都会按顺序等待每个Promise完成,再执行循环体。这种场景下看起来像是简化了变量声明,但这只是for await...of的基础用法。
场景2:遍历异步可迭代对象
如果iterableWithPromises是异步可迭代对象(实现了Symbol.asyncIterator接口,比如Node.js的可读流、自定义异步迭代器),普通for...of代码会直接“失效”:
- 普通
for...of只能遍历同步可迭代对象,它会直接把异步迭代器next()方法返回的Promise当成迭代元素,而不是等待Promise resolve后取出真正的迭代值。 for await...of则会自动处理异步迭代器的next()返回的Promise,等待其resolve后,把结果里的value作为循环变量。
举个自定义异步迭代器的例子:
// 一个异步可迭代对象,每隔100ms生成一个数字 const asyncIterable = { [Symbol.asyncIterator]() { let count = 0; return { async next() { await new Promise(resolve => setTimeout(resolve, 100)); return count < 3 ? { value: count++, done: false } : { done: true }; } }; } }; // 用for await...of可以正常遍历,依次输出0、1、2 (async () => { for await (const num of asyncIterable) { console.log(num); } })(); // 用普通for...of的结果完全不同 (async () => { for (const p of asyncIterable) { // p是next()返回的Promise对象,不是我们要的数字 console.log(p); // 直接输出Promise { <pending> } // 就算加await,拿到的也是迭代结果对象,需要手动取value const q = await p; console.log(q.value); // 这样才能拿到0、1、2,但逻辑和for await...of完全不同 } })();
总结
- 普通
for...of+await只能处理元素是Promise的同步可迭代对象,本质是遍历同步迭代器的元素,再逐个等待Promise。 for await...of是专门为异步可迭代对象设计的语法,它会自动处理迭代过程中的异步操作,取出真正的迭代值,同时也兼容元素是Promise的同步可迭代对象。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

