一、async/await 核心简介
async/await 是 ES7 推出的异步语法糖,基于 Promise 封装,彻底解决了传统 Promise 链式调用代码嵌套层级深、可读性差、维护困难的「回调地狱」问题。
该语法可以让异步代码像同步代码一样自上而下顺序执行,逻辑清晰、调试简单,是 Vue 项目接口请求、异步逻辑处理的主流规范写法。
核心语法规则:
- async :修饰函数,写在函数定义前,标识该函数为异步函数,返回值为 Promise 对象
- await :修饰异步操作,只能在 async 函数内部使用,作用是阻塞代码,等待异步请求执行完成后,再执行后续代码
- 异常捕获 :await 异步报错无法直接捕获,必须搭配 try/catch 捕获异常
二、传统 Promise 链式调用(弊端演示)
在多个接口串行依赖调用场景下(后一个接口依赖前一个接口的返回数据),传统 Promise 的 then 链式调用会出现多层嵌套,代码冗余、层级混乱、极难维护。
业务场景:先通过手机号获取用户属地,再根据属地省市信息请求充值面额列表
javascript
methods: {
// 获取用户所属属地
getLocation(phoneNum) {
return axios.post('/location', { phoneNum });
},
// 根据属地省市获取充值面额列表
getFaceList(province, city) {
return axios.post('/location', { province, city });
},
// 传统Promise链式调用(多层嵌套,可读性差)
getFaceResult() {
this.getLocation(this.phoneNum).then(res => {
if (res.status === 200 && res.data.success) {
let province = res.data.province;
let city = res.data.city;
// 二次嵌套调用,层级堆积
this.getFaceList(province, city).then(res => {
if (res.status === 200 && res.data.success) {
this.faceList = res.data
}
})
}
}).catch(err => {
console.log(err)
})
}
}
传统写法痛点:多接口串行嵌套、代码层级深、逻辑割裂、异常处理集中、后续扩展难度大。
三、async/await 标准优雅写法(推荐生产使用)
使用 async/await 重构后,异步逻辑完全同步化,代码扁平化无嵌套,执行顺序一目了然,完美适配接口串行依赖场景。
javascript
methods: {
// 获取用户所属属地
getLocation(phoneNum) {
return axios.post('/location', { phoneNum });
},
// 根据属地省市获取充值面额列表
getFaceList(province, city) {
return axios.post('/location', { province, city });
},
// async/await 优雅串行调用
async getFaceResult() {
// 所有异步操作统一捕获异常
try {
// 等待第一个接口执行完成,获取返回结果
let location = await this.getLocation(this.phoneNum);
// 上一个接口执行完毕,才会执行后续逻辑
if (location.data.success) {
let province = location.data.province;
let city = location.data.city;
// 等待第二个依赖接口执行完成
let result = await this.getFaceList(province, city);
if (result.data.success) {
this.faceList = result.data;
}
}
} catch (err) {
// 统一处理所有异步异常
console.log(err);
}
}
}
四、核心执行逻辑解析
- 给函数添加 async 修饰,将普通函数转为异步函数,支持内部使用 await;
- await 强制阻塞代码执行,等待
getLocation接口请求完毕、返回结果后,才会向下执行; - 解析第一个接口返回的省市数据,作为第二个接口的请求参数;
- 再次通过 await 等待
getFaceList接口执行完成,最终赋值渲染数据; - 所有异步请求的报错、异常,全部被 try/catch 统一捕获,避免页面报错崩溃。
五、async/await 关键使用规则(必记)
- await 必须在 async 函数内部使用,普通函数内直接使用 await 会报语法错误;
- await 默认串行执行,代码自上而下依次执行,天然适配接口依赖场景;
- 必须搭配 try/catch:Promise 链式可单独 catch,await 异步异常无法自动捕获,不加 try/catch 会导致程序报错中断;
- async 函数始终返回 Promise 对象,可正常搭配 then 继续链式调用,兼容性极强;
- 无依赖的并行接口不建议串行 await,会造成不必要的请求耗时。
六、核心优势总结
- 代码扁平化:彻底消除回调嵌套,告别回调地狱,代码整洁优雅;
- 逻辑更清晰:异步代码同步化写法,执行顺序直观,可读性大幅提升;
- 维护性更强:新增、删减异步逻辑无需调整嵌套层级,迭代成本低;
- 异常统一处理:通过 try/catch 集中捕获所有异步异常,报错管理更规范。
七、场景选型总结
- 接口串行依赖、多步骤异步逻辑 :优先使用 async/await(本文核心场景);
- 简单单次异步请求:可使用简易 Promise then 写法;
- 无依赖并行请求 :搭配
Promise.all+ async/await 实现最优性能。