Async/Await 是 ES2017 引入的语法糖,用于简化 Promise 的使用,让异步代码看起来像同步代码。它的核心原理是:
-
async:声明一个函数为异步函数 -
await:暂停代码执行,等待 Promise 结果 -
与传统 Promise 对比
// Promise 写法function fetchData() {return fetch('url').then(response => response.json()).catch(err => console.error(err));}// Async/Await 写法async function fetchData() {try {const response = await fetch('url');return response.json();} catch (err) {console.error(err);}}
2. 基本语法规则
2.1 声明异步函数
使用 async 关键字修饰函数:
// 函数声明async function myAsyncFunc() { /* ... */ }// 箭头函数const myAsyncFunc = async () => { /* ... */ };// 对象方法const obj = {async fetchData() { /* ... */ }};
2.2 使用 await
await 只能在 async 函数内部使用:
async function example() {const result = await somePromise; // 等待 Promise 完成console.log(result);}
2.3 返回值自动包装
异步函数始终返回 Promise:
async function foo() {return 42; // 自动包装为 Promise.resolve(42)}foo().then(result => console.log(result)); // 42
3. 错误处理
3.1 try/catch 捕获错误
async function fetchUser() {try {const response = await fetch('/api/user');const data = await response.json();return data;} catch (error) {console.error('请求失败:', error);throw error; // 可选择继续抛出错误}}
3.2 结合 .catch()
async function example() {const data = await fetchData().catch(err => {console.error('备用处理:', err);return defaultValue;});}
4. 并行执行技巧
4.1 并行执行多个异步操作
使用 Promise.all:
async function fetchAll() {const [users, posts] = await Promise.all([fetch('/api/users'),fetch('/api/posts')]);// 等待所有结果完成后再处理const userData = await users.json();const postData = await posts.json();return { userData, postData };}
4.2 按需执行
// 串行执行const result1 = await task1();const result2 = await task2(result1);// 并行执行(无依赖关系时)const [r1, r2] = await Promise.all([task1(), task2()]);
5. 常见使用场景
5.1 网络请求
async function getUserPosts(userId) {const user = await fetch(`/users/${userId}`);const posts = await fetch(`/posts?userId=${userId}`);return { user, posts };}
5.2 文件操作(Node.js)
const fs = require('fs').promises;async function readFiles() {const file1 = await fs.readFile('file1.txt', 'utf8');const file2 = await fs.readFile('file2.txt', 'utf8');return file1 + file2;}
5.3 定时器控制
function delay(ms) {return new Promise(resolve => setTimeout(resolve, ms));}async function countdown() {console.log(3);await delay(1000);console.log(2);await delay(1000);console.log(1);}
6. 注意
6.1 避免阻塞陷阱
错误写法:
// 这会依次执行等待,导致总时间叠加const a = await task1(); // 等待 1sconst b = await task2(); // 再等待 1s → 总 2s// 正确并行写法 → 总 1sconst [a, b] = await Promise.all([task1(), task2()]);
6.2 循环中的 await
// 依次执行(可能不符合预期)for (const url of urls) {await fetch(url); // 每个请求串行执行}// 并行执行所有请求const promises = urls.map(url => fetch(url));await Promise.all(promises);
6.3 顶级 await
在 ES2022+ 的模块中可使用:
// 模块顶层直接使用const data = await fetchData();export default data;
7. 总结
| 关键点 | 说明 |
|---|---|
async 函数返回值 |
总是返回 Promise |
await 作用范围 |
只能在 async 函数内部使用 |
| 错误处理优先级 | 优先使用 try/catch |
| 并行执行优化 | 合理使用 Promise.all |
| 避免过度串行化 | 注意循环中的 await 使用 |
| 浏览器兼容性 | 现代浏览器/Node.js 7.6+ 支持 |
-
优先使用
async/await替代 Promise 链式调用 -
复杂的异步逻辑使用
Promise.all/Promise.race优化 -
始终处理错误(要么
try/catch,要么.catch()) -
在需要兼容旧环境时使用 Babel 转译
掌握 async/await 能让异步代码更易读、更易维护,是现代 JavaScript 开发的必备技能!
![]() |
Austin Liu 刘恒辉
Project Manager and Software Designer E-Mail:lzhdim@163.com Blog:https://lzhdim.cnblogs.com 欢迎收藏和转载此博客中的博文,但是请注明出处,给笔者一个与大家交流的空间。谢谢大家。 |




浙公网安备 33010602011771号