JS中的EventLoop

JS中的EventLoop

一、宏任务和微任务

**宏任务(macrotask):**主代码块(整体代码)、setTimeout、setInterval、 setImmediate 等 。

微任务( microtask ): Promise.then、 process.nextTick 等。

二、 EventLoop 的执行流程

  1. 一开始将整体代码作为一个宏任务执行。
  2. 从上到下的执行过程中,同步代码直接执行,宏任务代码开放入宏任务队列,微任务代码放入微任务队列。
  3. 当前的宏任务执行完后,检查微任务队列,没有的话直接执行下一步,如果有则依次执行微任务队列。其中执行的微任务里包含宏任务或微任务时,同(2)的操作,直到微任务队列为空。
  4. 查看宏任务队列里还有没有任务,有的话拿出来执行。
  5. 新拿到的宏任务,回到第(2)步,依次执行,直到 宏任务和微任务队列都为空 。

三、案例

1、简单的带解释的哈

Promise.resolve().then(()=>{
  console.log('Promise1')  
  setTimeout(()=>{
    console.log('setTimeout2')
  },0)
});
setTimeout(()=>{
  console.log('setTimeout1')
  Promise.resolve().then(()=>{
    console.log('Promise2')    
  })
},0);
console.log('start');

过程:

  1. 将整体代码作为第一个宏任务,从下到上执行
  2. 遇到 Promise.resolve().then ,将其整个代码块放入微任务队列
  3. 遇到 setTimeout ,将其整个代码块放入宏任务队列
  4. 遇到 console.log('start') ,直接执行,输出 start
  5. 第一个宏任务执行完毕,检查微任务队列,发现里面有Promise.resolve().then代码块,执行该代码块。
  6. 遇到 console.log('Promise1') ,直接执行,输出 Promise1
  7. 遇到 setTimeout ,将其整个代码块放入宏任务队列
  8. 该微任务执行完后,发现此时微任务队列里已经没有任务了
  9. 去检查宏任务队列,发现里面有两个 setTimeout 任务,将最早的 setTimeout取出执行(第2步的那个)
  10. 遇到 console.log('setTimeout1') ,直接执行,输出 setTimeout1
  11. 遇到 Promise.resolve().then ,将其整个代码块放入微任务队列
  12. 此时的宏任务执行完了,检查微任务队列,发现里面有任务,是Promise.resolve().then(第11步那个),执行微任务队列
  13. 遇到 console.log('Promise2'),直接执行,输出 Promise2
  14. 该微任务执行完后,发现此时微任务队列里又双叒叕没有任务了,(那就接着来繁琐的循环吧)
  15. 去检查宏任务队列,发现里面还有一个宝贝任务诶,取出setTimeout执行(这次是第7步的那个哦)
  16. 遇到 console.log('setTimeout2') ,直接执行,输出 setTimeout2
  17. 这个宏任务也搞好了,再去瞅瞅微任务队列,妈耶没得了(开心)
  18. 在瞅瞅宏任务队列,妈耶也没得,终于搞好了,再也不用转来转去了

答案:

// start
// Promise1
// setTimeout1
// Promise2
// setTimeout2

2、async/await

async function fn1(){
    console.log(1)
    await fn2()
    console.log(2)
}
async function fn2(){
    console.log(3)
}
fn1()

new Promise(function(resolve){
    console.log(4)
    resolve()
}).then(()=>{
    console.log(5)}
)

答案:

// 1
// 3
// 4
// 2
// 5

解释:

是不是有点和你想的不一样, 简单来说,await前面的是同步,await后面的是微任务

await fn2()
console.log(2)
// 等价于
fn2().then(() => {
    console.log(2)
})
// Promise.then是微任务,这下了解吧

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('setTimeout0') 
},0)  
setTimeout(function(){
    console.log('setTimeout3') 
},3)  
setImmediate(() => console.log('setImmediate'));
process.nextTick(() => console.log('nextTick'));
async1();
new Promise(function(resolve){
    console.log('promise1')
    resolve();
    console.log('promise2')
}).then(function(){
    console.log('promise3')
})
console.log('script end')

答案:

script start
async1 start
async2
promise1
promise2
script end
nextTick
async1 end
promise3
setTimeout0
setImmediate
setTimeout3

**解释:**不解释了,自己慢慢瞅去,我当年也是这么过来的(难受)

4、微任务套微任务

async function a1 () {
    console.log('a1 start')
    await a2()
    console.log('a1 end')
}
async function a2 () {
    console.log('a2')
}

console.log('script start')

setTimeout(() => {
    console.log('setTimeout')
}, 0)

Promise.resolve().then(() => {
    console.log('promise1')
})

a1()

let promise2 = new Promise((resolve) => {
    resolve('promise2.then')
    console.log('promise2')
})

promise2.then((res) => {
    console.log(res)
    Promise.resolve().then(() => {
        console.log('promise3')
    })
})
console.log('script end')

答案:

script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout

**解释:**你觉得这里应该有解释吗

5、关于 process.nextTick 的补充

process.nextTick(() => console.log(1));
Promise.resolve().then(() => console.log(2));
process.nextTick(() => console.log(3));
Promise.resolve().then(() => console.log(4));

答案:

1
3
2
4

不是,1,2,3,4 哦

解释:

process.nextTick 虽然是像微任务那样执行的,但是还是有不同的

  • 两者不在同一个队列里,process.nextTick 是一个独立于 eventLoop 的任务队列
  • process.nextTick 优先于微任务执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值