前言

关于 Promiseasync/await 的使用,许多开发者已经相当熟悉。但是,当涉及到事件循环机制和输出结果的题目时,你敢说你都能正确回答吗?让我们通过几个例子来深入探讨。

例子分析

例子 1

async function async1() {
  await new Promise((resolve, reject) => {
    resolve()
  })
  console.log('A')
}

async1()

new Promise((resolve) => {
  console.log('B')
  resolve()
}).then(() => {
  console.log('C')
}).then(() => {
  console.log('D')
})

// 最终结果:B A C D

例子 2

async function async1() {
  await async2()
  console.log('A')
}

async function async2() {
  return new Promise((resolve, reject) => {
    resolve()
  })
}

async1()

new Promise((resolve) => {
  console.log('B')
  resolve()
}).then(() => {
  console.log('C')
}).then(() => {
  console.log('D')
})

// 最终结果:B C D A

疑问

基本相同的代码为何会有不同的输出结果?让我们继续深入了解。

async 函数返回值

在讨论 await 之前,我们先来讨论一下 async 函数如何处理返回值。async 函数会根据返回值的类型,引起 JavaScript 引擎对返回值的不同处理方式。

结论

  • 非 thenable、非 promise:不等待
  • thenable:等待 1 个 then 的时间
  • promise:等待 2 个 then 的时间

例子 1

async function testA() {
  return 1;
}

testA().then(() => console.log(1));
Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));

// (不等待)最终结果:1 2 3

例子 2

async function testB() {
  return {
    then(cb) {
      cb();
    }
  };
}

testB().then(() => console.log(1));
Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));

// (等待一个then)最终结果:2 1 3

例子 3

async function testC() {
  return new Promise((resolve, reject) => {
    resolve()
  })
}

testC().then(() => console.log(1));
Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));

// (等待两个then)最终结果:2 3 1

await 右值类型区别

2.1 非 thenable

async function test() {
  console.log(1);
  await 1;
  console.log(2);
}

test();
console.log(3);

// 最终结果:1 3 2

2.2 thenable类型

async function test() {
  console.log(1);
  await {
    then(cb) {
      cb();
    },
  };
  console.log(2);
}

test();
console.log(3);

Promise.resolve()
  .then(() => console.log(4))
  .then(() => console.log(5))
  .then(() => console.log(6))
  .then(() => console.log(7));

// 最终结果:1 3 4 2 5 6 7

2.3 Promise类型

async function test() {
  console.log(1);
  await new Promise((resolve, reject) => {
    resolve()
  })
  console.log(2);
}

test();
console.log(3);

Promise.resolve()
  .then(() => console.log(4))
  .then(() => console.log(5))
  .then(() => console.log(6))
  .then(() => console.log(7));

// 最终结果:1 3 2 4 5 6 7

总结

  • async 函数的返回值永远都是 Promise,无论值本身是什么。
  • await 会根据右侧表达式的类型,决定是否等待以及等待的时间。
  • async/await 是用同步的方式执行异步操作。

通过这些例子和分析,我们可以看到 async/awaitPromise 在 JavaScript 中的强大功能和灵活性。理解它们的工作原理和正确使用它们,可以帮助我们写出更高质量的代码。

最后修改:2024 年 11 月 18 日
如果觉得我的文章对你有用,请随意赞赏