带 async 关键字的函数,它使得函数的返回值必是promise对象
如果 async 关键字函数返回的不是promise,会自动用Promise.resolve() 包装
如果 async 关键字函数显式的返回 promise,以你返回的promise为准
async function fn1(){
return 123
}
function fn2(){
return 123
}
console.log(fn1()) // Promise {<resolved>: 123}
console.log(fn2()) // 123
async function async1() {
await async2()
console.log( 'async1 end' )
}
async function async2() {
console.log( 'async2' )
}
async1()
console.log( 'script start' )
实践的结论是:从右向左的。先打印async2,后打印script start
也就是遇到await后,阻塞的是除await当前行之后的代码!
右侧表达式的结果,就是await要等的东西
等到之后,对await来说,分2种情况
- 不是promise对象
- 是 promise 对象
如果不是promise,await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果
如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果
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' )
执行顺序:
- 同步代码 console.log( ‘script start’ )
- 将 setTimeout 放入宏任务队列
- 执行 async1() 函数 console.log( ‘async1 start’ )
- 分析下 await async2()
先得到 await 右侧表达式的结果. 执行 async2() ,打印同步代码 console.log( ‘async2’ ),并且 return Promise.resolve(undefined);
await 后,中断async函数,先执行async外的同步代码 - 被阻塞后,执行async之外的代码
执行 new Promise(), console.log( ‘promise1’ ) - promise.then(),发现这个是微任务,所以暂时不打印,只是推入当前宏任务的微任务队列中。
- 打印同步代码 console.log( ‘script end’ )
- 执行完同步代码后,执行 await Promise.resolve(undefined) 了,类似于Promise.resolve(undefined) .then((undefined) => { })
微任务队列,先进先出原则:
- 任务1, console.log( ‘promise2’ )
- 任务2 ,Promise.resolve(undefined),语句结束后,后面的代码不再被阻塞,所以打印 console.log( ‘async1 end’ )
宏任务队列,console.log(‘setTimeout’)