为什么我的异步函数在之前的承诺被实现之前被执行?

kyl*_*jw2 5 javascript

我写了一个小程序,比较了.then()方法和async/await方法之间的承诺的实现。代码运行正确,但是,输出的接收顺序出乎意料。有人可以解释为什么输出按当前顺序排列吗?

const backend = (num) => {
  const someVar = new Promise((resolve, reject) => {
    if (num % 2 === 0) {
      resolve(`The number, ${num}, is even.`);
    } else {
      reject(`The number, ${num}, is odd.`);
    }
  })
  return someVar;
}
const builtInFuncs = (num) => {
  backend(num)
    .then(message => console.log(message))
    .catch(message => console.log(message));
}
const asyncAwait = async(num) => {
  try {
    const response = await backend(num);
    console.log(response);
  } catch (error) {
    console.log(error);
  }
}

builtInFuncs(2);
builtInFuncs(3);

asyncAwait(4);
asyncAwait(5);
Run Code Online (Sandbox Code Playgroud)

我期望的输出是:

The number, 2, is even.
The number, 3, is odd.
The number, 4, is even.
The number, 5, is odd.
Run Code Online (Sandbox Code Playgroud)

我收到的输出是:

The number, 2, is even.
The number, 4, is even.
The number, 5, is odd.
The number, 3, is odd.
Run Code Online (Sandbox Code Playgroud)

Jar*_*ith 2

对于微任务解析,每个方法调用都单独排队。所以执行顺序是这样的:

  • 第一次调用已排队
  • 第二个调用已排队
  • 第三次调用已排队
  • 第四次调用已排队
  • 第一次.then火灾,控制台记录。
  • 第二次.then火灾,拒绝,.catch处理程序排队(未调用)。
  • 调用 async/await、console.logged
  • 第二次调用 async/await、拒绝、catch 块排队。
  • 解决.catch了,console.logged。
  • catch 块解析,最终日志。

在评论中支持 Barmar 关于切换捕获顺序的想法,然后。

为了更简单地说明(清楚?),考虑一个计数器和一个先递增然后递减它的 Promise 函数:

let i = 0;
const log = Promise.resolve()
  .then(() => console.log(++i))
  .then(() => console.log(--i));

log();
log();
Run Code Online (Sandbox Code Playgroud)

这将打印 1 2 1 0 而不是 1 0 1 0。如果你仔细想想,这有一定的意义:方法链可能在任何步骤失败,因此运行时将第一个调用排队,而第二个调用只.then排队一旦第一个完成。否则,如果第一个调用失败(被拒绝),则必须返回并从回调队列中删除推测排队的第二个调用。

  • 您可以通过将顺序交换为“.catch(...).then(...)”来演示这一点 (2认同)