javascript - 等待单个 promise 与异步迭代器的异步解析顺序

标签 javascript typescript asynchronous async-await es6-promise

所以这是基于我在开发一个用于简化异步生成器或迭代器的包时所做的发现。

通常,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 )

[...]

  1. 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/

相关文章:

javascript - 如何在脚本标签内使用html编码的xss攻击向量触发xss?

javascript - 用于模块导入的 Typescript 编译

unit-testing - Nodejs 单元测试网址

c# - 如何从 Windows 服务总线订阅获取未处理的消息计数?

java - 如何实现带有超时的 Runnable?

javascript - 如何在 JavaScript 字符串中使用\n

c# - 使用page或httphandler输出javascript变量

javascript - 函数定义中的引用变量

javascript - typescript : Add an autoincrement id attribute of each object in array

typescript - 你如何推断​​ Vue 3 组件中的 Prop 类型?