学习笔记 — JavaScript事件机制(promise/setTimeout/async/await)

事件循环:执行同步任务,然后执行微任务,再执行下一个宏任务,如此循环下去。

常见的宏任务:

  • script代码块
  • setTimeout
  • setTimeInterval     
  • dom
  • ajax
  • postMessage         

常见的微任务:

  •  process.nextTick
  • promise.then  catch  finally
  • async 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')
    })
    async1()
    new Promise(function (resolve) {
      console.log('promise1') 
      resolve()
    }).then(function () {
      console.log('promise2')
    })
    console.log('script end')

注意:new Promise的代码是同步执行的

分析过程如下图:

图解:先打印 script start,然后将setTimeout加入宏任务队列,继续执行async1函数,接着打印

async1 start,遇到await时,await 右边的函数同步执行,打印出async2,await下面的代码会加入微任务队列(微任务队列的第一条微任务),然后退出async1函数,继续向下来到new Promise,new Promise的代码是同步执行的,所以打印出promise1,遇到resolve,将then加入微任务队列(微任务队列的第二条微任务),然后打印出script end。

到此同步栈执行完毕,去微任务队列执行微任务。

微任务1,打印出async1 end

微任务2,打印出promise2

到此微任务队列清空,再去执行宏任务。

只有一个宏任务,打印出settimeout。

到此,所有任务执行完毕,最终的输出结果如下:

'script start'

'async1 start'

'async2'

'promise1'

'script end'

'async1 end'

'promise2'

'settimeout'

总结:

1. new Promise里的代码是同步执行的 

2. async函数调用的时候去函数里面同步执行,遇到await时,await右侧的代码同步执行,await下面的代码会加入微任务队列。

题目二

console.log('1');   
setTimeout(function() {
  console.log('2');
  process.nextTick(function() {
    console.log('3');
  })
  new Promise(function(resolve) {
    console.log('4');
    resolve();
  }).then(function() {
    console.log('5')
  })
})
process.nextTick(function() {
  console.log('6'); 
})
new Promise(function(resolve) { 
  console.log('7');
  resolve();
}).then(function() {
  console.log('8')
})

setTimeout(function() {
  console.log('9');
  process.nextTick(function() {
    console.log('10');
  })
  new Promise(function(resolve) {
    console.log('11');
    resolve();
  }).then(function() {
    console.log('12')
  })
})

这道题目乍一看有点长,但是不要怕,一步一步分析和梳理。

分析过程如下:

第一步,先拆解出同步,和宏任务,微任务,如下图:

 上图中依次标出了宏任务和微任务,没有标出的就是同步执行的代码。

先执行同步代码,依次打印出 1  7。

接下来来到微任务队列,由2条微任务

微任务1,打印出6

微任务2,打印出8

微任务执行完毕。

然后执行宏任务,有2个宏任务

宏任务1,执行过程中,产生了2个微任务1-1和微任务1-2

 console.log('2')和console.log('4')是宏任务1中的同步任务,先执行,然后再去执行微任务1-1和微任务1-2。所以在宏任务1执行过程中的打印顺序为:2  4  3  5

宏任务1执行完毕,继续执行下一个宏任务2。

 与宏任务1同理,先执行绿色框框的代码,再去微任务队列执行微任务2-1和2-2。

宏任务2的打印顺序为:9  11  10  12

到此为止,所有任务全部执行完毕。

最终的打印顺序为:1  7  6  8  2  4  3  5  9  11  10  12

这样一层层分析下来,发现也不是很难。

题目三

const promise = new Promise((resolve, reject) => {
  resolve("10")
}).then(res => {
  console.log("res1:", res) 
  return 9
}).then(res => {
  console.log("res2:", res)
  return 8
}).then(res => {
  console.log("res3:", res)
  let promise2=new Promise((resolve,reject)=>{
    resolve("p2")
  }).then(res=>{
    console.log(res)
    setTimeout(function(){
      console.log("setTimeout2")
    },0)
  })
})

console.log('aaa')
setTimeout(function(){
  console.log("setTimeout1")
},0)

const promise1 = new Promise((resolve, reject) => {
  console.log("p1")
  resolve(989)
}).then(res => {
    console.log(res)
    return 990
}).then(res=>{
  console.log(res)
  return 991
}).then(res=>{
  console.log(res)
  return 0
})

这个题目看起来更复杂了,但是不要怕,还是逐步进行拆解,一点一点分析。

首先进行第一步拆解,只有2条绿色的同步语句,和2个微任务(其余的代码先暂时不考虑)。

 依次执行,先打印aaa,再打印p1。同步执行完成,扫描微任务队列,此时微任务队列只要2条,按顺序执行。

微任务1:打印res1:10,然后执行return 9,也就是产生了新的微任务1-1,排在微任务2的后面。

 

微任务2:打印989。执行return 990,产生了新的微任务2-1,排在微任务1-1的后面。

 

微任务1和微任务2执行完之后,此时,微任务队列还有2条新加入的微任务1-1和微任务2-1,分别执行。

微任务1-1:打印res2:9,执行return 8,产生了新的微任务1-1-1,加入队列中,排在微任务2-1的后面。

 

微任务2-1:打印990,执行return 991,产生了新的微任务2-1-1,加入队列中,排在微任务1-1-1的后面。

微任务1-1和微任务2-1执行完之后,微任务队列还有2条新加入的微任务1-1-1和微任务2-1-1,依次执行。

微任务1-1-1:打印res3:8,在执行时又产生了新的微任务1-1-1-1,排在微任务2-1-1的后面。

微任务2-1-1:打印991,没有再产生新的任务。接下来执行新的微任务1-1-1-1。

微任务1-1-1-1:打印p2,然后产生了宏任务2,排在宏任务1的后面。

 到这里,所有的微任务都执行完毕,然后再扫描宏任务队列,执行宏任务1和宏任务2.

宏任务1:打印settimeout1。

宏任务2:打印setTimeout2。

至此,所有的任务都执行完了,最终的输出如下:

 这个题目的分析过程有点长,嵌套多层,但是一层层分析,发现本质还是事件循环的机制。

上面3个题目都搞懂了,那么遇到同类型的应该都没有问题。

还有很多其他类型的题目,有时间再继续补充.....

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值