← 返回目录

15. async / await

async/await 就是用同步写法写异步代码,比 Promise 链式更清晰。

核心两个:
async 函数——自动返回 Promise
await——等 Promise 完成

坑:await 只能在 async 函数里、await 后面是 Promise、try/catch 捕获错误、多个 await 可以并行用 Promise.all

15.1 互动演示(模拟三顿外卖)

点按钮,看 await 怎么"拦住"代码一步步走。

15.2 知识点讲解

① .then 接结果 → await 等结果

以前 .then 像"留个电话,好了打给我";await 像"站在原地等,好了再走下一步"。

// 一个返回 Promise 的函数
function getData() {

// 造一个承诺
  return new Promise(resolve => {

// 500 毫秒后兑现
    setTimeout(() => resolve("数据来了"), 500);
  });

// 以前:.then 回调接
}

// 好了再打给我
getData.then(data => {

// 拿到结果
  console.log(data);

// 现在:async 函数里 await 等
});

// 门口挂牌"办异步业务"
async function main() {

// ★ 在这里停住,等它出结果
  let data = await getData();

// 等到了再打印
  console.log(data);
}

// 调一下
main();

await 会"拦住"代码:上一行等完,才执行下一行。结果直接当普通变量用,不用再写回调函数。

② 失败处理:.catch → try...catch

以前失败走 .catch,现在用同步代码那套 try...catch 接住就行。

// 以前
// 成功走 then
getData.then(d => console.log(d))

// 失败走 catch
  .catch(err => console.log("失败:", err));

// 现在
// async 函数里
async function main() {

// 包一层 try
  try {

// 失败会像普通异常一样抛出
    let data = await getData();

// 成功就打印
    console.log(data);

// 失败被 catch 接住
  } catch (err) {

// catch 接住
    console.log("失败:", err);
  }
}

await 的 Promise 失败时,会像普通代码一样"抛出异常",try...catch 就能接住,跟同步代码的错误处理完全一致。

③ 多个 await:按顺序一个个等

// async 函数里
async function main() {

// 等第一个
  let a = await getData("第一个");

// 第一个完了才等第二个
  let b = await getData("第二个");

// 打印第一个结果
  console.log(a);

// 打印第二个结果
  console.log(b);
}

注意:两个 await 是串行等待(总耗时相加)。如果两个请求互不依赖,应该用 Promise.all([p1, p2]) 并行,总耗时只取最长的——这是性能优化点。

④ 注意:await 只能在 async 里,async 返回值被包成 Promise

// await 离开 async 函数会报错
// await getData;
// ★ 报错(顶层要 ES2022 模块才支持)
// async 函数 return 的值,外面要 then / await 才能拿
// async 函数
async function fn() {

// 你以为返回 123
  return 123;
}

// 123
fn.then(v => console.log(v));

如果你写了 const x = asyncFn 然后直接把 x 当数字用,会发现 x 是个 Promise 对象。因为 async 函数的返回值会自动被包成 Promise——外面必须再 await.then 才能拿到真实值。

15.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:接口请求后再渲染页面、登录后拉用户信息再跳转、按顺序执行的多步异步任务、封装"等结果再继续"的业务逻辑。

② 常见的问题:await 写在普通函数外面报错;async 函数 return 出来的直接当值用(其实是 Promise);多个不相关的 await 串行导致页面慢。

③ 解决思路:await 必须写在 async 函数或模块顶层;async 返回值再 await 一层;无依赖并发用 Promise.all([p1, p2]);失败一律 try...catch 包起来。

一句话:async 声明异步函数,await 在里面等结果,异步代码写得像同步;失败用 try...catch 接。

本页重点

API作用参数返回值代码示例
async function声明这是一个办异步业务的函数-一个 Promiseasync function run() {}
await p在这一行停下来等 Promise 的结果一个 Promise它的结果await getData();
try...catch接住 await 失败抛出来的异常代码块错误原因p.catch(e => console.log(e));