← 返回目录

8. async / await

async/await 就是把异步代码写得像同步一样,不用链式 then。

核心两个:
1. async 函数——返回 Promise
2. await——等 Promise 完成,后面写同步代码

坑:await 只能在 async 函数里、await 后面是 Promise、用 try/catch 捕获错误

打个比方:以前用 .then 链,像接力赛,一棒接一棒;现在用 await,像你自己一步一步走,走到一个路口等一下,等人来了继续走——读起来就像你平时说话写作文一样自然。

8.1 互动演示(await 串行等待)

点按钮,看 await 怎么让异步代码按顺序走。

8.2 知识点讲解

1. 四条核心规则(背下来不犯错)

async/await 用起来很简单,但有四条铁律必须记住:

// 规则1:async 必须写在函数前面
// 只有 async 函数里面才能写 await!
// 这里面才能用 await
async function getData() {
}

// 规则2:await 后面必须跟一个 Promise 对象
// await getUser → getUser 返回一个 Promise
// await 123 → 后面不是 Promise (没意义)

// 规则3:await 会"暂停"当前函数,等 Promise 出结果了再往下走
// 注意:只暂停当前这个函数!不会卡住整个页面!
// 页面照样能点、能滚、能输入

// 规则4:await 的失败不会自动捕获!必须用 try/catch 包起来
// 不然失败了程序直接崩,没人管

如果你在普通函数里写了 await——会直接语法报错——因为 await 只能在 async 函数内部用。如果你忘了 try/catch,接口失败时整个函数静默崩溃,页面啥反应没有——因为 await 的失败会像普通报错一样抛出来,没人接就飞了。

2. 标准模板(照着抄就行)

// 标准模板:async 函数 + try/catch + 一行一个 await
async function loadData() {
  // 第一行:等用户接口完成
  try {
    // await 会暂停在这里,等 getUser 返回了再往下走
    // 第二行:拿到 user.id 了,再查订单
    let user = await getUser;
    // 上一行等完了才执行这一行
    // 第三行:两个数据都拿到了
    let order = await getOrder(user.id);
    console.log(user, order);

  // 上面任何一行 await 失败,都会跑到这里来
  } catch (err) {
    console.log("接口出错了:", err);
  }
// 最后调用这个函数
}
// 调用函数必须加括号
loadData();

顺序有依赖的接口,一行一个 await,从上到下写,比 .then 链直白多了——读的时候就像在读普通的同步代码,完全不用想异步的事。

3. 对比:then 链 vs async/await

同样的逻辑,两种写法放一起对比:

// ===== 写法一:then 链(上节课学的) =====
getUser
  .then(function (user) {
    // 要 return 才传给下一个
    return getOrder(user.id);
  })
  .then(function (order) {
    console.log(order);
  })
  .catch(function (err) {
    console.log(err);
  });

// ===== 写法二:async/await(本课学的
async function main() {
  try {
    // 等完了再下一行
    let user = await getUser;
    let order = await getOrder(user.id);
    console.log(order);
  } catch (err) {
    console.log(err);
  }
}
// 调用函数必须加括号
main();
// 两种写法效果完全一样!但 await 读起来自然多了

await 只能在 async 函数里用——如果你在普通的 <script> 顶层直接写 await,会报错,因为顶层不是 async 函数。要么包一个 async 函数,要么用 <script type="module"> 模块模式。

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

可能在什么地方用:

1. 项目里调接口的主流写法——所有页面的接口调用都用 async/await
2. 有顺序依赖的多个接口(登录→查订单→查详情)
3. 配合上节课封装的 request 函数使用。

常见的问题:

1. 普通函数里写了 await——语法报错
2. 忘了 try/catch,接口失败时静默崩溃
3. 以为 await 卡住了整个页面——其实只卡当前函数
4. 忘了在 async 函数前面加 async 关键字。

解决思路:

1. 模板背熟:async function + try { await } catch 三件套
2. 每行 await 都假设它可能失败,必须有 catch 兜底
3. 不确定时,把代码复制到 Console 跑一下,报错信息会告诉你哪行出了问题。

一句话:async 声明异步函数,await 等 Promise 结果;顺序依赖一行一个 await,从上到下读;失败用 try/catch 接;await 只暂停当前函数,不卡页面。

8.3 课后作业(融入本节)

练习四:async/await 实战把上节课用 then 链写的请求调用,改写成 async/await 版本,用 try/catch 捕获错误。要求:1. 先 await 拿到用户
2. 再 await 用用户 id 查订单
3. 任何一步失败都能在 catch 里看到错误。

本页重点

API作用参数返回值代码示例
async function声明一个自动包成 Promise 的函数返回:Promiseasync function load() { }
await等异步结果出来再往下走入参:一个 Promise返回:异步结果的值let data = await getUser();
try{}catch(e)接住 await 抛出来的错catch 里是错误对象不让程序崩掉try { await load(); } catch (e) { }