nodejs Event Loop

作者: sweetBoy_9126 | 来源:发表于2019-02-01 17:49 被阅读9次
1.前置知识
  • node.js
    是一个可以运行js的平台
    包括fs模块、http模块以及JS引擎(v8)

  • js引擎(单线程)
    同一时间只做一件事情,但是他也可以同一时间做多件事请,因为它有兄弟(其他线程)帮他做

比如:
对于一个ajax请求get('/1.json'),若果这个请求需要100ms,那么我在这100ms内触发一个点击事件让它打印出一个1可以吗?
答:可以,虽然说js是单线程,但是它可以主要是因为它的请求让它的兄弟网络模块去做了,这时候js就处于空闲状态,等到网络模块请求完成就会通知js,js然后就会去执行一个回调

2.nodejs Event loop

2.1 当nodejs启动时,会执行三件事情

  1. 初始化event loop
  2. 开始执行脚本
  3. 进入event loop

2.2. 处理event loop经历的几个阶段(初始化的时候不会有这几个阶段)

上面的几个阶段中我们只需要了解红框中的三个就可以了,并且每一个阶段都有自己的一个队列

  • timers阶段
    处理setTimeout和setInterval中到时的回调函数,对于timers中队列的处理,setTimeout或setInterval中的函数都添加到队列里,同时记下来这些函数什么时间被调用到了调用时间就调用,没到时间就进入下一阶段,然后会停留在poll阶段
  • poll阶段
    轮询阶段
    比如上面说的让兄弟(其他线程处理的请求任务),在这个阶段会一直去问执行相关任务的模块任务执行完了没有,一旦任务执行完成,相关的数据就会放到一个回调里面然后加入到poll的队列中,也就是除了timers阶段外的所有回调都是在poll这个阶段处理的。poll阶段会一直重复检查刚才timers里没有到时间的计时器有没有到时间,如果到时间了,就直接通过check到达timers阶段通知timers执行这个回调,然后从timers队列中清除
    check阶段
    只处理setImmediate

2.3. 通过一个例子更加清楚的理解timers是怎么执行的

比如一开始有两个计时器一个4ms一个100ms
正常情况:当第一次timers的时候4ms已经到了所以直接执行里面的函数然后从队列中清除,然后第二个100ms并没有到,就会进入poll阶段停留,poll阶段会一直读时间问100ms有没有到,如果到了就直接通过check到timers然后通知它100ms到了执行相关的回调,从队列中清除
特例:因为poll从4ms一直等到100ms所以这段空闲的时间如果有另一个请求执行完了比如说是在90ms执行完了,那么这个时候它会去执行这个回调,但是这个函数调用也是需要时间的如果说调用用了20ms那么也就是说会在110ms的时候处理完这个函数的调用,也就是会错过100ms这个时间点,那么就会在110ms的时候通过check通知timers执行100ms那个回调

2.4. 关于setTImeout和setImmediate的执行顺序
答:正常情况下是setImmediate先执行,只有第一次启动nodejs的情况下timers里的定时器到时间了才可能setTimeout先执行。

原因:因为nodejs启动会执行三件事,开始执行脚本也就是执行你页面的代码,这时候会执行你的setTImeout,然后才会去处理event loop,而从执行脚本到处理event loop中间也需要时间,setTimeout最小的时间是4ms,如果从执行脚本到处理event loop花了5ms时间,那么一进入timers就会发现时间到了就会立刻处理回调,所以这时候setTimeout就会先执行

nextTick

进入每个阶段前都会执行,包括nodejs启动的时候也会执行

setTimeout(()=>{
  console.log('timeout')
})
setImmediate(()=>{
  console.log('immediate')
})
process.nextTick(()=>{
  console.log('next tick')
})
//next tick
//timeout
//immediate
Macro Task(宏任务)&Micro Task(微任务)

妈Ma 咪Mi
先执行完一个宏任务再去执行一个微任务,微任务每次都要清空
setTimeout后面的回调还有当前的脚本代码都是宏任务
nextTick和Promise都属于微任务

上图中setTimeout里面的回调是宏任务所以会放到宏任务的下一个任务队列中,而执行完一个宏任务后紧接着要执行一个微任务promise里面的是微任务,所以接着执行的是2,最后执行3

重要题目:

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

let promise = new Promise((resolve, reject)=>{
    console.log(1)
    resolve()
})
promise.then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

上面代码执行顺序是?
答:
script start
1
promise1
promise2
setTimeout
原因:promise里面的代码时立即执行的所以在script start后紧接着是1,而setTImeout里面的回调是宏任务,当前代码就是宏任务,所以需要在下个微任务后执行,promise.then里面的代码都是微任务,所以会先pormise最后setTimeout

相关文章

  • 性能优化2.1笔记

    event-loop https://nodejs.org/en/docs/guides/event-loop-t...

  • iOS RunLoop由浅入深

    Event Loop Event Loop事件循环机制,如javascript的事件循环,以及依赖其的nodejs...

  • event loop

    精华结论 浏览器的 Event Loop 遵循的是 HTML5 标准,而 NodeJs 的 Event Loop ...

  • Event loop

    为什么要了解Event loop?理解Event loop,对于浏览器(或者nodejs)处理事件的过程会有更透彻...

  • 不要在nodejs中阻塞event loop

    简介 我们知道event loop是nodejs中事件处理的基础,event loop中主要运行的初始化和call...

  • Nodejs Event Loop

    Nodejs Event Loop 什么是Nodejs Node.js 是一个javascript runtime...

  • Nodejs 解读event loop的事件处理机制

    摘要:1. nodejs 为什么要存在一个event loop的事件处理机制?2. event loop的事件处理...

  • NodeJs event loop

    V8有个task queue,IO event,timeout,interval事件会往task queue放入c...

  • nodejs event loop

    1.线程的问题 2.各个方法优先级的问题 需要知道宏任务,微任务的概念。process.nextTick() 3....

  • nodejs Event Loop

    1.前置知识 node.js是一个可以运行js的平台包括fs模块、http模块以及JS引擎(v8) js引擎(单线...

网友评论

    本文标题:nodejs Event Loop

    本文链接:https://www.haomeiwen.com/subject/kyddsqtx.html