一文吃透 JS 异步终极方案:async/await 原理、用法与实战技巧
前言
在 JavaScript 异步编程发展历程中,从最早期回调函数引发的回调地狱,再到Promise链式调用优化异步代码,虽然解决了多层嵌套痛点,但满屏的.then()依旧让代码可读性大打折扣。
而async/await作为 ES7 推出的异步语法糖,基于 Promise 和生成器实现,彻底让异步代码拥有同步代码的书写风格,成为目前前端项目中最主流的异步写法。今天全方位拆解async/await核心知识点、执行机制、易错点以及实战选型技巧。
一、核心概念通俗理解
1. 关键字释义
- async:异步标识,修饰在函数前面,声明该函数为异步函数特点:异步函数执行不会阻塞主线程后续同步代码,且隐式返回 Promise 对象
- await:直译
async wait,意为异步等待特点:只能写在 async 函数内部,暂停当前 async 函数内部代码执行,等待异步操作完成
2. 诞生原因
Promise 解决了回调地狱,但大量链式.then()堆砌,代码语义混乱、纵向嵌套冗长,逻辑阅读难度高。async/await应运而生,简化 Promise 调用,以同步思维编写异步逻辑,大幅提升代码简洁度与可读性。
3. 底层依托
async/await并非全新语法,底层依托两大技术实现:
- Promise:承接异步状态、成功 / 失败结果
- Generator 生成器:实现代码暂停、恢复执行的协程能力
二、深入解析 async 异步函数
1. 基础语法
只需在普通函数前添加async关键字,即可定义异步函数
// 定义异步函数
async function sayHello() {
return "Hello async/await";
}
2. 核心特性:隐式返回 Promise
正常返回值:async 函数内部普通返回值,自动被Promise.resolve()包裹
async function fn() {
return 100;
}
// 等价于普通Promise写法
function fn2() {
return Promise.resolve(100);
}
console.log(fn()); // Promise {<fulfilled>: 100}
抛出错误:函数内部抛出异常,自动被Promise.reject()包裹
async function errFn() {
throw new Error("异步执行失败");
}
console.log(errFn()); // Promise {<rejected>: Error}
3. 调用异步函数
async 函数调用方式和普通函数一致,想要获取最终结果,需通过.then()接收:
async function timeout() {
return "异步执行完成";
}
// 调用并获取结果
timeout().then(res => console.log(res));
// 主线程同步代码优先执行
console.log("我优先执行,不受异步阻塞");
执行结论:async 函数内部逻辑异步执行,不会阻塞主线程同步代码运行。
三、深度掌握 await 等待机制
1. await 等待规则
- 核心限制:await 只能存在于 async 函数中,普通函数直接使用直接报错
- 等待对象
- 优先等待Promise 对象:阻塞当前 async 函数内部代码,等待 Promise 状态变为
resolved/rejected,获取最终结果 - 等待普通值 / 普通函数:V8 引擎自动封装为
resolved状态的 Promise,直接返回值
- 优先等待Promise 对象:阻塞当前 async 函数内部代码,等待 Promise 状态变为
2. 基础使用示例
// 模拟异步请求,返回Promise
function getMsg() {
return new Promise(resolve => {
setTimeout(() => resolve("后端数据"), 1000);
});
}
// 使用async+await接收异步结果
async function getData() {
// 等待异步执行完成,拿到结果赋值
const res = await getMsg();
console.log(res); // 1秒后打印:后端数据
}
getData();
3. 串行异步执行(经典场景)
多个异步操作存在先后依赖,使用 await 串行执行,写法极简:
// 2秒后数值翻倍
function doubleNum(num) {
return new Promise(resolve => {
setTimeout(() => resolve(num * 2), 2000);
});
}
// 串行依次执行异步
async function calcTotal() {
let n1 = await doubleNum(10);
let n2 = await doubleNum(20);
let n3 = await doubleNum(30);
console.log(n1 + n2 + n3); // 6秒后输出 120
}
calcTotal();
console.log("主线程同步代码先行执行");
四、EventLoop 执行顺序(高频面试考点)
核心执行原则
- 遇到
await:仅阻塞当前 async 函数内部后续代码,不会阻塞全局主线程 - 主线程优先执行所有同步代码,同步执行完毕后,再执行微任务
- await 暂停的代码会进入微任务队列,宏任务最后执行
经典例题 1
async function fn1() {
console.log(1);
await fn2();
console.log(2);
}
async function fn2() {
console.log("fn2执行");
}
fn1();
console.log(3);
// 输出顺序:1 → fn2执行 → 3 → 2
经典例题 2
console.log(0);
async function test() {
console.log(100);
let x = await 200;
console.log(x);
console.log(200);
}
test();
console.log(300);
// 输出顺序:0 → 100 → 300 → 200 → 200
五、错误捕获与异常处理
await 等待的 Promise 一旦状态变为rejected,会直接抛出运行异常,必须通过try/catch捕获异常:
async function request() {
try {
// 异步请求报错
const res = await Promise.reject("接口请求失败");
console.log(res);
} catch (error) {
// 统一捕获异常
console.log("错误信息:", error);
}
}
request();
六、实战场景:async/await 与 Promise 选型
1. 单异步请求
简单单请求、需要单独捕获错误:优先使用 Promise.then/catch,写法更轻便
// Promise写法
getUserInfo()
.then(res => console.log(res))
.catch(err => console.log(err));
// async/await写法
async function getUser() {
try {
const res = await getUserInfo();
} catch(e) {}
}
2. 多层嵌套异步(依赖执行)
优先使用 async/await,彻底告别嵌套地狱,逻辑清晰直观
// 老式回调嵌套
getUser(id, (res) => {
getOrder(res.uid, (order) => {
getPay(order.id)
})
})
// async/await优雅写法
await getUser(id);
await getOrder(uid);
await getPay(orderId);
3. 无依赖并发异步(重点避坑)
错误写法(串行执行,耗时翻倍)
// 两个异步互不依赖,串行执行浪费时间
await req1();
await req2();
正确写法(并发执行,节省时间)借助Promise.all实现并发请求,所有异步执行完成后统一处理
// 并发执行,同时发起请求
await Promise.all([req1(), req2()]);
console.log("所有请求全部完成");
七、必记使用注意事项
async函数可以不写await,依旧会返回 Promise 对象- await 只暂停当前函数内部代码,全局主线程不受影响
- Promise 创建时不会生成微任务,只有调用
resolve/reject才会推入微任务队列 - 批量异步优先
Promise.all,杜绝无效串行等待 - 所有 await 异步操作,建议统一用
try/catch做异常兜底
总结
async定义异步函数,隐式返回 Promise,不阻塞主线程;await暂停异步函数内部代码,等待异步结果,仅可在 async 内使用;- async/await 简化 Promise 链式调用,实现同步写法写异步逻辑;
- 简单异步用 Promise,嵌套 / 流程化异步用 async/await,并发异步搭配
Promise.all; - 异步异常统一通过
try/catch捕获,避免程序崩溃。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)