簡體   English   中英

等待單個承諾與異步迭代器的異步解析順序

[英]Async resolution order for await single promise vs async iterators

因此,這是基於我在處理包以簡化異步生成器或迭代器時所做的發現。

通常,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(反應,參數)

[...]

  1. 對於在反應中反應中,在原來的插入順序,執行

    一種。 執行 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 得到解決需要兩個 microticks。

這就是異步迭代器中發生的事情。 當您調用.next ,會返回一個 Promise 並存儲在迭代器內部隊列中。 同時,異步生成器函數的執行還在繼續。 然后,當異步迭代器yields (在您的情況下是在一個 microtick 之后),它會解析隊列中的下一個承諾。 由於承諾解析是另一個微任務,所以總共需要兩個滴答。

resolve();
// 1 microtick
await promise; // generators await yielded promises implicitly
yield; 
// 1 microtick
for await(const _ of iterator)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM