async/await 就是用同步写法写异步代码,比 Promise 链式更清晰。
核心两个:
① async 函数——自动返回 Promise
② await——等 Promise 完成
坑:await 只能在 async 函数里、await 后面是 Promise、try/catch 捕获错误、多个 await 可以并行用 Promise.all。
以前 .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 接住就行。
// 以前
// 成功走 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 就能接住,跟同步代码的错误处理完全一致。
// 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 函数会报错
// 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 才能拿到真实值。
① 可能在什么地方用:接口请求后再渲染页面、登录后拉用户信息再跳转、按顺序执行的多步异步任务、封装"等结果再继续"的业务逻辑。
② 常见的问题:await 写在普通函数外面报错;async 函数 return 出来的直接当值用(其实是 Promise);多个不相关的 await 串行导致页面慢。
③ 解决思路:await 必须写在 async 函数或模块顶层;async 返回值再 await 一层;无依赖并发用 Promise.all([p1, p2]);失败一律 try...catch 包起来。
| API | 作用 | 参数 | 返回值 | 代码示例 |
|---|---|---|---|---|
| async function | 声明这是一个办异步业务的函数 | - | 一个 Promise | async function run() {} |
| await p | 在这一行停下来等 Promise 的结果 | 一个 Promise | 它的结果 | await getData(); |
| try...catch | 接住 await 失败抛出来的异常 | 代码块 | 错误原因 | p.catch(e => console.log(e)); |