第 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(实现自动执行器) 吗?

这是高级必会题。

相关推荐
donecoding26 分钟前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化
风骏时光牛马30 分钟前
Raku正则匹配与数据批量处理实操案例
前端
nbwenren33 分钟前
2026实测:Gemini 3 镜像站视觉能力实践——拍照原型图,一键生成 HTML+CSS 代码
前端·css·html
Lee川36 分钟前
Prisma 实战指南:像搭积木一样设计古诗词数据库
前端·数据库·后端
许彰午1 小时前
我手写了一个 Java 内存数据库(二):B+ 树的插入与分裂
java·开发语言·面试
jinanwuhuaguo1 小时前
(第二十九篇)OpenClaw 实时与具身的跃迁——从异步孤岛到数字世界的“原住民”
前端·网络·人工智能·重构·openclaw
广州华水科技1 小时前
深度测评2026年单北斗GNSS位移监测系统推荐,与高口碑变形监测设备一同引领行业新风尚
前端
Alice-YUE2 小时前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
是上好佳佳佳呀3 小时前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记