async/await是什么
async/await 是ES2017(ES8)提出的基于Promise的解决异步的最终方案。
async
async是一个加在函数前的修饰符,被async定义的函数会成为异步函数,异步函数的返回值会自动封装到一个Promise对象里,最后默认返回一个Promise对象。
async function fn() {
return 20
}
let result = fn()
//返回的是一个Promsie对象
console.log(result)
await
await 也是一个修饰符
await 修饰的如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行
await只能放在async定义的函数内,或es模块的顶级作用域中。可以理解为等待。所以它不会阻塞async外面的代码,而async里在await后的代码必定依赖于await返回的结果,如果不依赖那么写在await前面即可,所以这个阻塞是不影响运行效率的
function sum(a, b) {
return new Promise(resolve => {
setTimeout(() => {
resolve(a + b)
})
})
}
async function fn3() {
let result3 = await sum(1, 2)
console.log(result3)
console.log('async里面')
}
fn3()
console.log('async外面');
//输出结果为:async外面 3 async里面
如果不是Promise对象:把这个非promise的东西当做await表达式的结果。
可以利用await来替代链式调用
async function fn() {
let result = await sum(1, 2)
result = await sum(result, 4)
result = await sum(result, 5)
console.log(result)
}
fn()
//返回值为12
await一般与async配合使用,如果async里没有await,那么它就与普通函数一样依次执行
async function fn() {
console.log(1);
console.log(2);
console.log(3);
}
fn()
console.log(4);
//输出结果为 1 2 3 4
等价于
function fn() {
return new Promise(resolve => {
console.log(1);
console.log(2);
console.log(3);
resolve()
})
}
fn()
console.log(4);
//输出结果为 1 2 3 4
当我们使用await调用函数后,当前函数后边的所有代码会在当前函数执行完毕后,被放入微任务队列
async function fn() {
console.log(111)
await console.log(222)
//await后边的代码,都会被放入到微任务队列中执行
console.log(333)
}
fn()
console.log(444);
输出结果为: 111 222 444 333
相当于
function fn() {
return new Promise(resolve => {
console.log(11)
console.log(22)
resolve()
}).then(r => {
console.log(33)
})
}
fn()
console.log(44)
try-catch
通过await调用异步代码时,需要通过try-catch来处理异常
try {
let result = await sum(1, 2)
console.log(result)
}catch(e) {
console.log('出错了~~~');
}
es模块
在html文件里我们无法直接使用await
<script>
await console.log(2333)
</script>
//报错:Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
将script标签变成模块就可以使用了
<script type="module">
await console.log(2333)
</script>
//控制台输出2333
还有我们在js文件里只能在async声明的函数里使用await
在mjs文件里则可以直接使用await
立即执行函数
我们在非es模块使用await时需要创建函数再调用函数
async function fn() {
await console.log('haha')
}
fn()
有点繁琐
可以用匿名的方式写成立即执行函数
(async () => {
await console.log('haha')
})()
这两个是等价的