JavaScript中的async/await原理与使用
字数 795 2025-11-04 08:34:40
JavaScript中的async/await原理与使用
描述
async/await是ES2017引入的异步编程解决方案,它基于Promise实现,但使用同步代码的书写方式来处理异步操作。async函数返回一个Promise对象,await用于等待Promise的解决结果,让异步代码具有更好的可读性和可维护性。
核心原理
- async关键字:标记函数为异步函数,自动将函数返回值包装为Promise对象。
- await关键字:暂停异步函数的执行,等待Promise解决,然后恢复执行并返回结果。
- 底层实现:通过Generator函数+自动执行器模拟,将异步操作转化为类似同步的执行流程。
具体步骤与示例
-
基本用法
- async函数声明:
async function fetchData() { return "data"; // 等价于Promise.resolve("data") } - await等待Promise结果(必须在async函数内使用):
async function example() { const result = await fetchData(); // 等待Promise解决后赋值 console.log(result); // "data" }
- async函数声明:
-
错误处理机制
- 使用try-catch捕获await表达式的错误:
async function loadData() { try { const data = await fetch("https://api.example.com/data"); if (!data.ok) throw new Error("请求失败"); return await data.json(); } catch (error) { console.error("加载失败:", error); } } - 也可通过.catch()处理(因async函数返回Promise):
loadData().catch(error => console.log(error));
- 使用try-catch捕获await表达式的错误:
-
并行优化策略
- 避免不必要的串行等待,使用Promise.all同时执行多个异步操作:
async function parallelTasks() { const [user, post] = await Promise.all([ fetch("/user"), fetch("/post") ]); // 两个请求同时发送,总时间取决于最慢的请求 }
- 避免不必要的串行等待,使用Promise.all同时执行多个异步操作:
-
底层实现模拟(简化版)
- 通过Generator+执行器模拟async/await行为:
function* generatorExample() { const data = yield fetch("/data"); // 类似await console.log(data); } // 自动执行器(类似Babel转换后的代码) function runGenerator(gen) { const g = gen(); function handle(result) { if (result.done) return; result.value.then(data => { handle(g.next(data)); // 将Promise结果传回生成器 }); } handle(g.next()); }
- 通过Generator+执行器模拟async/await行为:
常见误区与注意事项
- await会阻塞当前async函数内的后续代码,但不会阻塞主线程(其他同步任务正常执行)。
- forEach等循环中直接使用await无法实现预期效果,需改用for...of循环:
// 错误示例 arr.forEach(async item => await task(item)); // 不会按顺序执行 // 正确写法 for (const item of arr) { await task(item); // 顺序执行 } - async函数中return的值会被自动包装为Promise.resolve(),抛出错误相当于Promise.reject()。
应用场景
- 替代Promise链式调用,简化多层异步依赖代码(如:登录→获取用户信息→加载配置)。
- 需要同步风格错误处理的复杂异步流程(如数据库事务操作)。
- 与Generator函数对比,async/await无需额外执行器,语言层面原生支持。