为什么 2 和 4 在 b 打印之前打印?

why 2 and 4 prints before b prints?

function first() {
  return new Promise(resolve => {
    console.log(2);
    resolve(3);
    console.log(4);
  });
}

async function f() {
  console.log(1);
  let r = await first();
  console.log(r);
  console.log(99);
}

console.log('a');
f();
console.log('b');

在上面的代码中显示了以下结果:

a
1
2
4
b
3
99

在我的理解中,当编译器命中await first()函数时,它将first()函数的执行推送到事件队列并暂停f()的执行,继续执行之后的所有内容f().所以执行顺序应该是:

a
1
b
2
4
3
99

显然,我理解错了。任何人都可以向我解释这是如何工作的吗?

查看这篇关于 Promise 的 executor 参数的 MDN 文章。

执行器函数被立即调用,即同步调用。

await 基本上是在等待承诺 resolution/rejection 但 await 语句之后的同步代码会立即执行。

类似地,进行 f() 调用,请注意,虽然 async 函数 return 一个承诺,但在 a 之后控制台中立即有 1

如果你不明白,请发表评论。 谢谢。

我认为这是真实发生的,请看评论和数字

function first() {
  return new Promise(resolve => {
    console.log(2); // 5. Print "2"
    resolve(3); // 6. call resolve(3), meaning it will set the resolveCallback state of Promise with 3. 
    console.log(4); // 7. print "4"
  });
}

async function f() {
  console.log(1); // 3. Print "1"
  let r = await first(); // 4. Call the first() method and await the result, control goes to first() 
                        // 8. Since first() method updated the state of resolveCallback, it will assign "3" to variable "r" 
  console.log(r); // 10. print "3" 
  console.log(99); // 11. print "99"
}

console.log('a'); // 1. Start print 'a'
f(); // 2. Since funtion f() is decoreated with async key word it is by default return a promise and control goes to f()
console.log('b'); // 9. Since control release from f() print "b"

简单来说,Promise 允许您 运行 一些异步代码 然后 运行 其他代码完成后取决于结果(是否失败或成功)。它是使用构造函数模式创建的。

签名:函数(resolveCallback, rejectCallback)

构造函数 returns 一个 Promise 对象,它跟踪它的 state,并且只能设置一次。这意味着resolver和rejector函数一起只能接收一个调用,状态不能从resolved变为rejected,反之亦然。

await 表达式导致异步函数执行暂停,直到 Promise 是 settled.once promise 被履行或拒绝,然后它恢复执行异步 function.In 平均时间它将继续执行异步函数之外的代码。

嗯,需要深入理解javascript中的"Task and Microtask execution"。 每个承诺都通过一些微任务队列处理,这些微任务队列在每个任务结束时 运行。

根据文档,只要没有其他 JavaScript 是 mid-execution,微任务队列就会在回调之后处理,并且在每个任务结束时处理。在微任务期间排队的任何其他微任务都将添加到队列的末尾并进行处理。

您可以在 https://javascript.info/microtask-queue 找到最佳解释。

如果您担心执行顺序,请在 Promise 中使用 setTimeout。 setTimeout 为其回调安排一个新任务,因此在这种情况下它将 运行 在当前任务之后

function first() {
  return new Promise(resolve => { setTimeout(()=>{
    console.log(2);
    resolve(3);
    console.log(4);
  }); });
}

async function f() {
  console.log(1);
  let r = await first();
  console.log(r);
  console.log(99);
}

console.log('a');
f();
console.log('b');