gpt4 book ai didi

javascript - 链式 promise 如何在微任务队列中排队

转载 作者:行者123 更新时间:2023-12-02 23:05:37 33 4
gpt4 key购买 nike

(async function() {
var a,b;

function flush(){
return new Promise(res => {
res(123)
})}

Promise.resolve().then(() => a = 1)
Promise.resolve().then(() => b = 2)

await flush();

console.log(a)
console.log(b)

})()

在此代码段中,ab 的值记录在控制台中。

(async function() {
var a;
var b;

function flush(){
return new Promise(res => {
res(123)
})}

Promise.resolve().then(() => a = 1).then(() => b = 2)

await flush();

console.log(a)
console.log(b)

})()

在这种情况下,a 的值记录为 1,而 b 未定义。

(async function() {
var a;
var b;

function flush(){
return new Promise(res => {
setTimeout(res)
})}

Promise.resolve().then(() => a = 1).then(() => b = 2)

await flush();

console.log(a)
console.log(b)

})()

这给出了与第一个代码段相同的结果,其中值a为1,b为2

我想了解,为什么 promise 链的行为与多个单独的 promise 不同

PS:我对微任务队列和事件循环有基本的了解。

最佳答案

运行 Node 12.3.1,我可以重现问题中所述的观察结果,将 setTimeout(res(123)) 更改为 setTimeout(() => res(123)) 后。

在 JavaScript 中,并发模型是事件循环,其中单个线程执行队列中的回调。

<小时/>

在第一个片段中,发生以下情况。

  1. 由于 Promise 已重新执行,.then 将回调 () => a = 1 添加到队列中。
  2. () => b = 2 已添加到队列中。
  3. await1 之后的代码 () => console.log(a); console.log(b)2 被添加到队列中。
  4. 第 1 步中的回调已运行,a 设置为 1
  5. b 设置为 2
  6. ab 已记录。

由于设置变量是在打印变量之前进行的,因此您会看到 1 和 2。

<小时/>

在第二个片段中:

  1. 回调() => a = 1.then添加到队列中
  2. 第一个 .then 返回一个新的 Promise,该 Promise 尚未解析,因为第一个回调尚未运行。然后第二个 .then() => b = 2 附加到待处理的 Promise。
  3. await 之后的代码 () => console.log(a); console.log(b) 被添加到队列中。
  4. 回调 () => a = 1 运行,并履行第 2 步中创建的 Promise。这会导致添加 () => b = 2到队列中。
  5. ab 已记录。
  6. b = 2 已运行,但这发生在 b 被打印之后,而 b未定义的
<小时/>

但是在 Firefox 中,所有三个片段的输出都是相同的。我设法通过添加异步来产生上述行为。Promise.resolve().then(async () => a = 1).then(() => b = 2)

这是一个显示相同问题的简化版本。Node 中为 1 5 2 3 4,Firefox 中为 1 2 3 5 4。

(async function() {
Promise.resolve()
.then(() => console.log(1))
.then(() => console.log(2))
.then(() => console.log(3))
.then(() => console.log(4))
await Promise.resolve()
console.log(5)
})()

但是如果将 await 更改为 .thenPromise.resolve().then(() => console.log(5))

您在两个平台上都获得 1 5 2 3 4。3

为什么?我用谷歌搜索并找到了这个: https://v8.dev/blog/fast-async

Node 12 通过 await 优化了一些额外的步骤,这之前需要额外的一次性 promise 和两个微标记。这似乎就是“5”在 Node 12 中提前两步的原因。

<小时/>
  1. 您可以使用简化的思维模型,await 将其余代码转换为回调。
  2. 事实上,“其余代码”也解决了异步函数创建的 Promise。
  3. 呵呵,所以 .thenawait 毕竟是不同的。

关于javascript - 链式 promise 如何在微任务队列中排队,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57605016/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com