第 28 题:async / await 的原理是什么?为什么说它是 Promise 的语法糖?(详细版)

async / await 的原理是什么?为什么说它是 Promise 的语法糖?(详细版)**

async/await 是现代 JS 异步编程的核心,面试官喜欢问:

  • async 到底返回什么?
  • await 是如何"暂停"的?
  • async/await 和 Promise 的关系是什么?
  • async/await 为什么会让人觉得像同步?

我们逐条说明。


一、async 的本质

任何 async 函数的返回值一定是 Promise。------ 无条件!

例子:

csharp 复制代码
async function demo() {
  return 123;
}

等价于:

javascript 复制代码
function demo() {
  return Promise.resolve(123);
}

如果 async 内部抛出异常:

javascript 复制代码
async function demo() {
  throw new Error("err");
}

等价于:

javascript 复制代码
function demo() {
  return Promise.reject(new Error("err"));
}

二、await 的本质

await 会暂停 async 函数的执行,把后续代码加入微任务队列(Promise.then)。

简化理解:

ini 复制代码
let x = await foo();

等价于:

ini 复制代码
foo().then(result => {
  x = result;
  // 恢复 async 函数执行
});

但关键差别是:

JS 主线程没有暂停,是 async 函数暂停了

主线程继续执行后面的代码。


三、await 的执行机制(最重要)

每次遇到 await:

  1. 执行 await 后面表达式,得到一个 Promise(如果不是,会自动包装成 Promise.resolve)
  2. 暂停当前 async 函数
  3. 把 await 后面的代码放到微任务队列
  4. 等待 Promise 完成后恢复执行

四、async/await = Generator + 自动执行器(自动 yield)

ES 语义上:

async/await 是 Generator + co 库的语法糖。

比如:

javascript 复制代码
async function test() {
  let r = await foo();
  console.log(r);
}

等价于 Generator:

javascript 复制代码
function* test() {
  let r = yield foo();
  console.log(r);
}

加上执行器(自动执行 Generator):

scss 复制代码
co(test);

所以:

await 就是自动 yield

async 就是自动执行 Generator 的包装器


五、为什么 async/await 写起来像同步?

因为:

  • JS 主线程继续执行
  • async 函数内部挂起(暂停)
  • 恢复时继续从上次断点执行

让代码结构看起来是同步顺序:

ini 复制代码
const a = await step1();
const b = await step2(a);
const c = await step3(b);

但本质上:

  • 每个 await 都是把后面的逻辑放入微任务队列
  • 整个过程是异步非阻塞的

六、async/await 的错误处理方式

try/catch :

javascript 复制代码
try {
  const data = await fetchData();
} catch (err) {
  console.log(err);
}

相当于:

scss 复制代码
fetchData()
  .then(...)
  .catch(...)

区别是:

✔ 错误流程和同步代码一样易读

✔ async/await 更适合复杂逻辑


七、最常考示例:输出顺序题

例题:

javascript 复制代码
async function test() {
  console.log(1);
  await Promise.resolve();
  console.log(2);
}

console.log(3);
test();
console.log(4);

输出顺序:

bash 复制代码
3       (主线程)
1       (执行 test 的同步部分)
4       (主线程继续)
2       (await 后的微任务)

为什么?

  • await 将后续放入微任务
  • 所以 2 最后执行

八、20 秒面试背诵版

async 函数会返回一个 Promise;函数内部抛错会等于返回 reject。
await 会暂停 async 函数,把后续逻辑加入微任务队列,等待 Promise 完成后继续执行。
本质上 async/await 是 Promise + Generator 的语法糖,让异步代码以同步写法表达。


要继续 第 34 题:手写一个 async/await(实现自动执行器) 吗?

这是高级必会题。

相关推荐
李剑一40 分钟前
uni-app实现本地MQTT连接
前端·trae
EndingCoder42 分钟前
Any、Unknown 和 Void:特殊类型的用法
前端·javascript·typescript
oden43 分钟前
代码高亮、数学公式、流程图... Astro 博客进阶全指南
前端
GIS之路1 小时前
GDAL 实现空间分析
前端
JosieBook1 小时前
【Vue】09 Vue技术——JavaScript 数据代理的实现与应用
前端·javascript·vue.js
pusheng20252 小时前
算力时代的隐形防线:数据中心氢气安全挑战与技术突破
前端·安全
起名时在学Aiifox2 小时前
前端文件下载功能深度解析:从基础实现到企业级方案
前端·vue.js·typescript
2501_941877983 小时前
从配置热更新到运行时自适应的互联网工程语法演进与多语言实践随笔分享
开发语言·前端·python
云上凯歌3 小时前
01 ruoyi-vue-pro框架架构剖析
前端·vue.js·架构