所以这是基于我在开发一个用于简化异步生成器或迭代器的包时所做的发现。
通常,promise 的执行顺序由调用时间决定,这意味着以下情况成立(在 Windows 和 Mac 上的 Chrome 和 Node 中)。
let resolve, promise = new Promise(r => resolve = r);
(async () => {
await promise
console.log('1st')
})();
(async () => {
await promise
console.log('2nd')
})();
resolve();
但是,在处理异步生成器或迭代器时,不遵守此顺序
let resolve, promise = new Promise(r => resolve = r);
async function* generator() {
yield promise
}
(async () => { // regular promise
await promise
console.log('1st')
})();
(async () => { // promise generator
for await (let _ of generator())
console.log('3rd (should be 2nd)')
})();
(async () => { // promise iterator
for await (let _ of [promise])
console.log('4th (should be 3rd)')
})();
(async () => { // regular promise again
await promise
console.log('2nd (should be 4th)')
})();
resolve();
我不确定“执行/决议顺序”是否是正确的术语,但是这个顺序是否有保证?有什么办法可以在节点或浏览器程序中保证此顺序吗?
最佳答案
保证 promise 解析顺序:
25.6.1.8 TriggerPromiseReactions ( reactions, argument )
[...]
For each reaction in reactions, in original insertion order, do
a. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, << reaction, arguments >>)
要了解迭代器的情况,请查看以下代码片段:
let resolve, promise = new Promise(r => resolve = r);
let chained = promise.then(it => Promise.resolve());
(async () => {
await chained;
console.log("2nd");
})();
(async () => { // regular promise
await promise
console.log('1st')
})();
resolve();
如您所见,当另一个 Promise 得到解决时,一个 Promise 也得到解决,这需要两个微时钟周期。
这就是异步迭代器中发生的情况。当您调用 .next
时,会返回一个 Promise 并将其存储在迭代器内部队列中。与此同时,异步生成器函数继续执行。然后,当异步迭代器yields
(在您的情况下是在一个微滴之后)时,它会解析队列中的下一个 promise 。由于 promise 解析是另一个微任务,因此总共需要两次滴答。
resolve();
// 1 microtick
await promise; // generators await yielded promises implicitly
yield;
// 1 microtick
for await(const _ of iterator)
关于javascript - 等待单个 promise 与异步迭代器的异步解析顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59263926/