1、基于 Promise 的 async 和 await
- 什么是 async 和 await 呢?
async(异步的) 与 await(等待) 一般作为一对“连体婴”存在,生来就是为 Promise 所服务的,可以说 async 和 await 就是 Promise 的进化版,是 Promise 的语法糖。
- 首先来说一说 async 的用法
async function async1(){ ... } //正确
const async async2 = function(){ ... } //错误
- 而 await 必须在 async 函数的内部使用,且必须为“直系”
- 示例:
async function async1(){
function f1(){
await console.log(1)
}
}
- 报错:Uncaught SyntaxError: await is only valid in async function
2、async 的本质
- async 的本质就是会隐式的返回一个 Promise 对象
(async function async1(){
return 'hello world'
})()
Promise {<resolved>: "hello world"} //返回值
- 可以看到,一个声明为 async 的函数,默认的返回值就是一个 Promise 对象,等同于
(async function async1(){
return Promise.resolve('hello world')
})()
3、await 的本质
- await 顾名思义就是等待一会,只要 await 声明的函数还没有返回,那么下面的程序是不会去执行的。这就是字面意义的等待一会(等待返回再去执行)。
- 一旦遇到await 就立刻让出线程,阻塞后面的代码,等候之后,对于await来说分两种情况
- 不是 Promise 对象。如果不是 Promise,await 会阻塞后面的代码,先执行 async 外面的同步代码,同步代码执行完毕后,在回到 async 内部,把 Promise 的东西,作为 await 表达式的结果
- 是 Promise 对象。如果它等到的是一个 Promise 对象,await 也会暂停 async 后面的代码,先执行 async 外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。
4、相关示例题目
题目1:
async function async1() {
console.log( 'async1 start' )
await async2()
console.log( 'async1 end' )
}
async function async2() {
console.log( 'async2' )
}
async1()
console.log( 'script start' )
//async1 start
//async2
//script start
//async1 end
- 要注意的是,,async2() 是作为同步函数来执行的,因此会在输出 aycnc1 start 后立刻输出 async2
题目2:
async function async1() {
console.log( 'async1 start' )
await async2()
console.log( 'async1 end' )
}
async function async2() {
console.log( 'async2' )
}
console.log( 'script start' )
setTimeout( function () {
console.log( 'setTimeout' )
}, 0 )
async1();
new Promise( function ( resolve ) {
console.log( 'promise1' )
resolve();
}).then( function() {
console.log( 'promise2' )
})
console.log( 'script end' )
- 打印结果:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
await 语句是同步的,await语句后面全部代码才是异步的微任务,
题目3:
async function t1 () {
console.log(1)
console.log(2)
await Promise.resolve().then(() => console.log('t1p'))
console.log(3)
console.log(4)
}
async function t2() {
console.log(5)
console.log(6)
await Promise.resolve().then(() => console.log('t2p'))
console.log(7)
console.log(8)
}
t1()
t2()
console.log('end')
- 打印结果:
1
2
5
6
end
t1p
t2p
3
4
7
8
题目4:
async function t1 () {
console.log(1)
console.log(2)
new Promise( function ( resolve ) {
console.log( 'promise3' )
resolve();
} ).then( function () {
console.log( 'promise4' )
} )
await new Promise( function ( resolve ) {
console.log( 'b' )
resolve();
} ).then( function () {
console.log( 't1p' )
} )
console.log(3)
console.log(4)
new Promise( function ( resolve ) {
console.log( 'promise5' )
resolve();
} ).then( function () {
console.log( 'promise6' )
} )
}
setTimeout( function () {
console.log( 'setTimeout' )
}, 0 )
async function t2() {
console.log(5)
console.log(6)
await Promise.resolve().then(() => console.log('t2p'))
console.log(7)
console.log(8)
}
t1()
new Promise( function ( resolve ) {
console.log( 'promise1' )
resolve();
} ).then( function () {
console.log( 'promise2' )
} )
t2()
console.log('end');
- 打印结果:
1
2
promise3
b
promise1
5
6
end
promise4
t1p
promise2
t2p
3
4
promise5
7
8
promise6
setTimeout
- 注意,await 下一行开始的代码必须等 await 语句执行完成后(包括微任务完成),才能执行。也就是说,只有运行后面语句,才把await语句后面的全部代码加入到微任务行列,所以,在遇到 await Promise 时,必须等 await Promise 函数执行完毕才能对 await 语句后面的全部代码加入到微任务中,所以,在等待await Promise.then微任务时,
-
运行其他同步代码。
-
等到同步代码运行完,开始运行 await promise.then 微任务。
-
await promise.then微任务完成后,把await语句后面的全部代码加入到微任务行列。