1. 微任务、宏任务
宏任务包括:setTimeout setInterval Ajax Dom事件
微任务: promise async/await
注意:微任务比宏任务的执行时间要早
使用异步的场景
定时任务 :seTimeout, setInverval
网络请求:ajax请求,动态<img>加载
事件绑定
2. 执行具体步骤顺序
- 先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中
- 遇到异步微任务则将异步微任务放入微任务队列中
- 当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行
- 微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
await 之后,做什么?
分两种情况:
1.不是promise对象
- 如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果
2.是promise对象
- 如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。
3. 面试试题
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' )
分析
1.直接打印同步代码 console.log(‘script start’)
首先是2个函数声明,虽然有async关键字,但不是调用我们就不看。然后首先是打印同步代码 console.log('script start')
2.将 setTimeout 放入宏任务队列
3.调用 async1( ),打印 内部同步代码 console.log( ‘async1 start’ )
4. 遇到await async2()
1.它先计算出右侧的结果,2.然后看到await后,中断async函数
- 先得到await右侧表达式的结果。执行async2(),打印同步代码console.log('async2'), 并且return Promise.resolve(undefined)
- await后,中断async函数,先执行async外的同步代码
被阻塞后,执行async之外的代码
5. 执行async2(),打印同步代码console.log('async2'),
6.执行new Promise(),Promise构造函数是直接调用的同步代码,所以 console.log( ‘promise1’ )
代码运行到promise.then()
代码运行到promise.then(),发现这个是微任务,所以暂时不打印,只是推入当前宏任务的微任务队列中。
7.打印同步代码console.log( ‘script end’ )
8.执行微任务 await 打印console.log( ‘async1 end’ )
9.执行微任务打印 promise2
10.执行宏任务 setTimeout 打印console.log(‘setTimeout’)
答案
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout