24. async await 原理是什么,会编译成什么
总结
async/await
是 JavaScript 中用于简化异步编程的语法糖。async
函数会返回一个Promise
对象。await
会暂停async
函数的执行,直到Promise
被resolve
或reject
。- 在底层实现中,
async/await
会被编译为基于Promise
和 生成器(Generator) 的状态机。
基本原理
1. async
函数
async
函数本质上是一个返回Promise
的函数。- 函数内部的返回值会被自动包装成一个
Promise.resolve(value)
。
async function foo() {return "hello";
}foo().then(console.log); // 输出: hello
等价于:
function foo() {return Promise.resolve("hello");
}
2. await
表达式
await
会暂停当前async
函数的执行,等待Promise
完成。- 本质上是将异步操作“同步化”,提高代码可读性。
async function getData() {const res = await fetch("https://api.example.com/data");const data = await res.json();return data;
}
编译过程(Babel 示例)
Babel 等工具在编译 async/await
时,会将其转换为基于 Generator
和 Promise
的结构。
原始代码
async function getData() {const res = await fetch("https://api.example.com/data");const data = await res.json();return data;
}
编译后代码(简化示意)
function _asyncToGenerator(fn) {return function () {var self = this,args = arguments;return new Promise(function (resolve, reject) {var gen = fn.apply(self, args);function _next(value) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);}function _throw(err) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);}_next(undefined);});};
}function getData() {return _getData.apply(this, arguments);
}function _getData() {_getData = _asyncToGenerator(/*#__PURE__*/ regeneratorRuntime.mark(function _callee() {var res, data;return regeneratorRuntime.wrap(function _callee$(_context) {while (1) {switch ((_context.prev = _context.next)) {case 0:_context.next = 2;return fetch("https://api.example.com/data");case 2:res = _context.sent;_context.next = 5;return res.json();case 5:data = _context.sent;return _context.abrupt("return", data);case 7:case "end":return _context.stop();}}}, _callee);}));return _getData.apply(this, arguments);
}
执行流程图示
async 函数执行↓
返回一个 Promise↓
执行函数体↓
遇到 await 表达式↓
将 await 后的表达式作为 Promise 执行↓
Promise resolve 后继续执行后续代码↓
最终返回值作为 Promise 的 resolve 值
核心概念
概念 | 说明 |
---|---|
async | 将函数变为异步函数,返回一个 Promise |
await | 等待一个 Promise 的完成,暂停函数执行 |
Promise | async/await 的底层实现机制 |
Generator | 编译时用于实现异步控制流 |
regeneratorRuntime | Babel 编译 async/await 所需的运行时支持 |
注意事项
await
只能在async
函数中使用,否则会报错。await
后的表达式不一定是Promise
,如果不是,会自动包装为Promise.resolve()
。- 使用
try/catch
处理await
抛出的错误。
async function safeFetch() {try {const res = await fetch("https://api.example.com/data");return await res.json();} catch (error) {console.error("请求失败:", error);}
}
最佳实践建议
场景 | 建议 |
---|---|
多个异步操作需串行 | ✅ 使用 await 简化流程 |
多个异步操作可并行 | ✅ 使用 Promise.all() |
避免 await 泄露作用域 | ❌ 不要滥用嵌套 async/await |
错误处理 | ✅ 总是配合 try/catch 使用 |
兼容性处理 | ✅ 使用 Babel + @babel/preset-env 转译支持旧环境 |