async/await 是 ES2017 的新语法,它是 Promise 的"语法糖"——说白了就是让异步代码写起来像同步代码一样。你不用写 .then.catch 那一串了,直接一行一行从上往下写,看起来就是普通的同步代码,但背后其实是异步在跑。这是现在项目里最主流的写法。
打个比方:以前用 .then 链,像接力赛,一棒接一棒;现在用 await,像你自己一步一步走,走到一个路口等一下,等人来了继续走——读起来就像你平时说话写作文一样自然。
async/await 用起来很简单,但有四条铁律必须记住:
// 规则1:async 必须写在函数前面
// 只有 async 函数里面才能写 await!
async function getData() {
// 这里面才能用 await
}
// 规则2:await 后面必须跟一个 Promise 对象
// await getUser → getUser 返回一个 Promise ✅
// await 123 → 后面不是 Promise ❌(没意义)
// 规则3:await 会"暂停"当前函数,等 Promise 出结果了再往下走
// 注意:只暂停当前这个函数!不会卡住整个页面!
// 页面照样能点、能滚、能输入
// 规则4:await 的失败不会自动捕获!必须用 try/catch 包起来
// 不然失败了程序直接崩,没人管
如果你在普通函数里写了 await——会直接语法报错——因为 await 只能在 async 函数内部用。如果你忘了 try/catch,接口失败时整个函数静默崩溃,页面啥反应没有——因为 await 的失败会像普通报错一样抛出来,没人接就飞了。
// 标准模板:async 函数 + try/catch + 一行一个 await
async function loadData() {
try {
// 第一行:等用户接口完成
// await 会暂停在这里,等 getUser 返回了再往下走
let user = await getUser;
// 第二行:拿到 user.id 了,再查订单
// 上一行等完了才执行这一行
let order = await getOrder(user.id);
// 第三行:两个数据都拿到了
console.log(user, order);
} catch (err) {
// 上面任何一行 await 失败,都会跑到这里来
console.log("接口出错了:", err);
}
}
// 最后调用这个函数
loadData(); // 调用函数必须加括号
顺序有依赖的接口,一行一个 await,从上到下写,比 .then 链直白多了——读的时候就像在读普通的同步代码,完全不用想异步的事。
同样的逻辑,两种写法放一起对比:
// ===== 写法一:then 链(上节课学的) =====
getUser
.then(function (user) {
return getOrder(user.id); // 要 return 才传给下一个
})
.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"> 模块模式。
可能在什么地方用:
① 项目里调接口的主流写法——所有页面的接口调用都用 async/await;② 有顺序依赖的多个接口(登录→查订单→查详情);③ 配合上节课封装的 request 函数使用。
常见的问题:
① 普通函数里写了 await——语法报错;② 忘了 try/catch,接口失败时静默崩溃;③ 以为 await 卡住了整个页面——其实只卡当前函数;④ 忘了在 async 函数前面加 async 关键字。
解决思路:
① 模板背熟:async function + try { await } catch 三件套;② 每行 await 都假设它可能失败,必须有 catch 兜底;③ 不确定时,把代码复制到 Console 跑一下,报错信息会告诉你哪行出了问题。
练习四:async/await 实战——把上节课用 then 链写的请求调用,改写成 async/await 版本,用 try/catch 捕获错误。要求:① 先 await 拿到用户;② 再 await 用用户 id 查订单;③ 任何一步失败都能在 catch 里看到错误。