因此,这是基于我在开发用于简化异步生成器或迭代器的程序包时所做的发现。
通常,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();
我不确定“执行/解决方案命令”是否是正确的术语,但是可以保证此命令吗?在Node或Browser程序中可以做些什么来保证此顺序?
答案 0 :(得分:2)
保证承诺解决顺序:
25.6.1.8 TriggerPromiseReactions(反应,参数)
[...]
对于反应中的每个反应,按照原始插入顺序,执行
a。执行EnqueueJob(“ PromiseJobs”,PromiseReactionJob,<<反应,参数>>)
要了解迭代器的工作原理,请查看以下代码段:
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
(在您的情况下,经过一个微滴标记)后,它将解析队列中的下一个诺言。由于承诺解决是另一个微任务,因此总共需要花费两个时间。
resolve();
// 1 microtick
await promise; // generators await yielded promises implicitly
yield;
// 1 microtick
for await(const _ of iterator)