浏览器和node下的 Event Loop

浏览器和node下的 Event Loop

什么是Event Loop

event loop “事件循环” 可以看作是一个执行模型。他一直在查找不同的事件并执行。

它主要是正对于js的异步处理。

  • 对于浏览器来说,event loop是在html5的规范中明确规定,对于不同浏览器厂商有不同的规定。

  • NodeJS的Event Loop 是基于libuv实现的。libuv对Eventloop有单独的实现

浏览器上的实现

在js中,任务队列的任务被分为:

  • MacroTask

    script(整体代码)setTimeout 等

  • MicroTask

    Promises 等

以上两个任务的执行顺序如下:

1. 浏览器从task队列中按照顺序取task执行
2. 检查microtask队列,若为空,执行下一个task,否则将microtask队列的任务执行完毕。
setTimeout(()=>{
    console.log('timer1')

    Promise.resolve().then(function() {
        console.log('promise1')
    })
}, 0)

setTimeout(()=>{
    console.log('timer2')

    Promise.resolve().then(function() {
        console.log('promise2')
    })
}, 0)
//浏览器执行结果
timer1
promise1
timer2
promise2

以上的实现逻辑为:

浏览器因为两个setTimeout作为两个MacroTask, 所以先输出timer1, 再执行microtask里的promise1,再输出timer2, 再执行microtask里promise2。

node 上的实现

nodejs的event loop分为6个阶段

  1. timers:执行setTimeout() 和 setInterval()中到期的callback。
  2. I/O callbacks:上一轮循环中有少数的I/Ocallback会被延迟到这一轮的这一阶段执行
  3. idle, prepare:队列的移动,仅内部使用
  4. poll:最为重要的阶段,执行I/O callback,在适当的条件下会阻塞在这个阶段
  5. check:执行setImmediate的callback
  6. close callbacks:执行close事件的callback。

以上六个阶段被分为以下两个队列:

  • NodeJs的Macrotask队列:
    1. Timers Queue
    2. IO Callbacks Queue
    3. Check Queue
    4. Close Callbacks Queue
  • NodeJs的microtask队列:
    1. Next Tick Queue:是放置process.nextTick(callback)的回调任务的
    2. Other Micro Queue:放置其他microtask,比如Promise等

具体的执行过程就如下:

  1. 执行全局Script的同步代码
  2. 执行microtask微任务,先执行所有Next Tick Queue中的所有任务,再执行Other Microtask Queue中的所有任务
  3. 开始执行macrotask宏任务,共6个阶段,从第1个阶段开始执行相应每一个阶段macrotask中的所有任务,这里是所有每个阶段宏任务队列的所有任务,在浏览器的Event Loop中是只取宏队列的第一个任务出来执行,每一个阶段的macrotask任务执行完毕后,开始执行微任务,也就是步骤2
  4. Timers Queue -> 步骤2 -> I/O Queue -> 步骤2 -> Check Queue -> 步骤2 -> Close Callback Queue -> 步骤2 -> Timers Queue …
setTimeout(()=>{
    console.log('timer1')

    Promise.resolve().then(function() {
        console.log('promise1')
    })
}, 0)

setTimeout(()=>{
    console.log('timer2')

    Promise.resolve().then(function() {
        console.log('promise2')
    })
}, 0)
//nodejs执行结果
timer1
timer2
promise1
promise2
//如果以上setTimeout交换位置,输出的结果也有不同

以上的逻辑为:

最初timer1和timer2就在timers阶段中。开始时首先进入timers阶段,执行timer1的回调函数,打印timer1,并将promise1.then回调放入microtask队列,同样的步骤执行timer2,打印timer2;
至此,timer阶段执行结束,event loop进入下一个阶段之前,执行microtask队列的所有任务,依次打印promise1、promise2。

总结

  • 浏览器按照一个MacroTask任务,所有MicroTask的顺序运行。
  • Node按照六个阶段根据不同的Macrotask队列顺序运行,并在每个阶段后面都会运行MicroTask队列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值