async
和 await
是 JavaScript 中用于处理异步操作的关键字,它们通常一起使用来简化异步代码的编写和阅读。
async:
async
用于声明一个函数,被声明的函数的函数体会被封装到一个 Promise 对象里,而函数的返回值就是 Promise 对象 的PromiseResult。
function fn() {
return Promise.resolve(10)
}
// 等价于
async function fn2() {
return 10
}
fn().then(r => console.log(r))
fn2().then(r => console.log(r))
结果输出两个10
- 异步函数内部可以包含
await
表达式,用于等待 Promise 对象的解析(或拒绝)。
async function sum(a, b) {
console.log(a + b)
return a + b
}
async function fn6() {
await sum(1, 8)
console.log(1)
console.log(2)
console.log(3)
}
fn6()
console.log(4)
执行结果
- 异步函数内部可以抛出错误,会导致返回的 Promise 对象被拒绝,并传递错误信息。
await:
- 当
await
后面跟随一个 Promise 对象时,它会暂停异步函数的执行,直到该 Promise 对象解析(或拒绝)为止/直到异步代码执行有结果时,才会将结果返回。
同上一个例子
async function sum(a, b) {
console.log(a + b)
return a + b
}
async function fn6() {
await sum(1, 8)
console.log(1)
console.log(2)
console.log(3)
}
fn6()
console.log(4)
执行结果
- 如果
await
后面的 Promise 对象解析为一个值,await
表达式的结果就是这个值;如果 Promise 被拒绝,await
表达式会抛出一个错误,可以通过try...catch
来捕获。
async function sum(a, b) {
return a + b
}
async function fn3() {
sum(123, 456)
.then(r => sum(r, 8))
.then(r => sum(r, 9))
.then(r => console.log(r))
// 当我们通过await去调用异步函数时,它会暂停代码的运行
// 直到异步代码执行有结果时,才会将结果返回
// 注意 await只能用于 async声明的异步函数中,或es模块的顶级作用域中
// await阻塞的知识异步函数内部的代码,不会影响外部代码
// 通过await调用异步代码时,需要通过try - catch来处理异常
try {
let result = await sum(123, 456)
result = await sum(result, 8)
result = await sum(result, 9)
console.log(result)
} catch (e) {
console.log("出错了~~")
}
}
- 使用
await
可以让异步代码像同步代码一样顺序执行,避免了回调地狱和嵌套的 Promise。
async function sum(a, b) {
return a + b
}
async function f() {
result = await sum(1, 1)
result = await sum(result, 1)
result = await sum(result, 1)
console.log(result)
}
function f1() {
sum(1, 1)
.then(r => sum(r, 1))
.then(r => sum(r, 1))
.then(r => console.log(r))
}
f()
f1()
结果
- await只能用于 async声明的异步函数中,或es模块的顶级作用域中
错误使用
await console.log(1)
报错
- 正确使用
- 把后缀名js改为mjs
- 在script标签内部加个type=“module”
- 把后缀名js改为mjs
<body>
<script type="module">
await console.log(1)
</script>
</body>
- await会阻塞异步函数内部的代码,不会影响外部代码
async function fn2() {
console.log(1)
await console.log(2)
console.log(3)
}
// 等价于
// function fn2() {
// return new Promise(resolve => {
// console.log(1)
// console.log(2)
// }).then(
// console.log(3)
// )
// }
fn2()
console.log(666)
执行结果
- 如果async声明的函数中没有写await,那么它里边就会依次执行。当我们使用await调用函数后,当前函数后边的所有代码会在当前函数执行完毕后,被放入到微任务队里中(await后边的所有代码,都会放入到微任务队列中执行)
async function fn2() {
console.log(1)
await console.log(2)
console.log(3)
}
// 等价于
function fn2() {
return new Promise(resolve => {
console.log(1)
console.log(2)
}).then(
console.log(3)
)
}
注意: await 那一句代码只会影响异步函数内,外部是正常运行。
- 通过await调用异步代码时,需要通过try-catch来处理异常
总之,async
函数用于声明一个异步函数,而 await
则用于暂停异步函数的执行,等待 Promise 对象解析。它们的结合可以使异步代码更加清晰、易于理解和编写。