Await-Async
async/await 是 Promise 的表达层。
#type / concept
#status / growing
#resource / javascript
#resource / ecmascript
[!info] related notes
- 所属 MOC: ecmascript异步, ecmascript-promises-and-async, ES6 新特性 MOC
- 前置概念: Promise
- 并列概念: promise链, js事件循环
- 异常边界: 异步错误处理
- 面试问法: Event Loop、宏任务和微任务怎么理解
- 关系笔记: ecmascript异步, ecmascript-promises-and-async
async / await
这一部分可以看作:
Promise 的更顺手、更像同步代码的写法。
但底层还是 Promise。
async 是什么
async 放在函数前,表示:
这个函数总是返回一个 Promise。
async function foo() {
return 123;
}
等价理解接近:
function foo() {
return Promise.resolve(123);
}
所以:
foo().then((value) => {
console.log(value); // 123
});
await 是什么
await 的意思是:
等待一个 Promise 完成,并拿到它成功后的值。
async function test() {
const value = await Promise.resolve(42);
console.log(value);
}
test();
输出:
42
为什么 await 看起来像同步
因为代码写法变成了这样:
async function fetchData() {
const user = await getUser();
const posts = await getPosts(user.id);
console.log(posts);
}
看起来像:
- 先拿 user
- 再拿 posts
- 再打印
这比 .then(...).then(...) 更符合人的阅读习惯。
但注意:
看起来像同步,底层仍然是异步调度。
await 不会阻塞整个 JS 线程
这是个特别容易误解的点。
async function test() {
console.log("A");
await Promise.resolve();
console.log("B");
}
console.log("start");
test();
console.log("end");
输出:
start
A
end
B
为什么?
test()开始执行,先输出A- 遇到
await,函数暂停 - 后面的
console.log("B")会被放到后续微任务里 - 主线程继续执行
end - 最后再执行
B
说明 await 只是暂停当前 async 函数内部后续逻辑,不是卡死整个程序。
await 后面可以跟什么
通常跟 Promise,但也可以跟普通值。
async function test() {
const a = await 123;
console.log(a);
}
普通值会被自动包装成已完成的 Promise。
try...catch
async/await 最常见的错误处理方式是:
async function test() {
try {
const value = await Promise.reject("error");
console.log(value);
} catch (err) {
console.log("caught:", err);
}
}
test();
这让异步错误处理写起来更像同步异常处理。
Promise 写法 vs async/await 写法
Promise 写法
getUser()
.then((user) => getPosts(user.id))
.then((posts) => {
console.log(posts);
})
.catch((err) => {
console.log(err);
});
async/await 写法
async function main() {
try {
const user = await getUser();
const posts = await getPosts(user.id);
console.log(posts);
} catch (err) {
console.log(err);
}
}
通常第二种更易读。
async/await 的本质
你可以这样记:
async:让函数返回 Promiseawait:把 Promise 的“后续逻辑”拆开写得像同步- 底层本质:还是 Promise + 微任务