async/await 的原理是什么?相比 Promise 有什么优势?
async/await 是 Generator + Promise 的语法糖,让异步代码看起来像同步代码。
原理
async 函数返回一个 Promise,await 暂停函数执行直到 Promise 完成:
// async/await
async function fetchData() {
const res = await fetch('/api') // 暂停,等 Promise resolve
const data = await res.json()
return data // 返回值被 Promise.resolve 包装
}
// 等价的 Promise 写法
function fetchData() {
return fetch('/api')
.then(res => res.json())
.then(data => data)
}本质:Generator 自动执行
// Generator 版本
function* fetchDataGen() {
const res = yield fetch('/api')
const data = yield res.json()
return data
}
// 自动执行器(简化版)
function run(gen) {
const it = gen()
function step(val) {
const { value, done } = it.next(val)
if (done) return value
return value.then(step)
}
return step()
}
run(fetchDataGen)优势
- 可读性好:代码结构像同步,没有回调嵌套
- 错误处理:可以用
try/catch捕获异步错误 - 调试方便:可以在
await后打断点
// Promise 链式调用
function process() {
return fetchA()
.then(a => fetchB(a))
.then(b => fetchC(b))
.catch(err => console.log(err))
}
// async/await 更清晰
async function process() {
try {
const a = await fetchA()
const b = await fetchB(a)
const c = await fetchC(b)
return c
} catch (err) {
console.log(err)
}
}注意事项
await只能在async函数内使用(顶层 await 需要 ES2022)await后的代码相当于.then()的回调,是微任务- 并发请求时不要用
await串行,应该用Promise.all:
// ❌ 串行,慢
const a = await fetchA()
const b = await fetchB()
// ✅ 并行,快
const [a, b] = await Promise.all([fetchA(), fetchB()])