nodejs 事件循环

41 阅读3分钟

经常面试喜欢问js的事件循环和node的区别 node的比js的可要复杂一点 先说一下js的,我只说10版本之后的,就不包括浏览器环境一些api了

js事件循环

个人理解的分类为 js 整个脚本代码 全局代码 js 异步事件: 各种的回调函数

异步事件分为宏任务-微任务 宏任务: 异步事件 (例如鼠标点击、键盘按键) 级别高 setTimeOut setInterval 请求的回调 微任务: promise then catch

整个流程代码是从上到下执行

举个白话的例子说明一下: 可以这么理解,执行顺序就像是考试做题,正常从上往下做,遇到不会的,难题(异步任务),拿两张新纸记录下来 稍难(微任务) 的一张, 特别难(宏任务) 的一张, 当前简单的做完了以后,拿过来稍难(微任务)得继续做,重复没有稍难的就拿过来特别难的,最终做完为止

就是在每一轮代码执行的过程最后都会把这一轮所产生的所有微任务执行完之后再进行下一轮开始 代码执行题可以看我文章 juejin.cn/post/723148…

事件循环 juejin.cn/post/684490…

node 事件循环

好了我们说正题了---nodejs的事件循环阶段 1,timers(定时器)阶段:在这个阶段,执行所有的setTimeout和setInterval回调。 2,pending callbacks阶段:在此阶段,执行那些在事件循环的早期阶段注册的回调。 3,idle, prepare阶段:这是node内部执行阶段。 4,poll(轮询)阶段:此阶段主要负责检索新的I/O事件。 5,check(检查)阶段:此阶段在轮询阶段之后,如果在轮询阶段没有设置timer,且轮询队列不为空,event loop将同步执行queue里面的回调,直到轮询队列为空。如果设置了setImmeadiate,poll queue将进入check阶段;如果没设定setImmeadiate,则会阻塞在poll queue阶段。 6,close callbacks阶段:在此阶段,执行关闭回调。

其实我们最关注的还是 timers poll check

image.png

一直在poll队列等待

image.png

如果有定时器里的函数先到时间放入到Timer事件循环里,check里也有 setImmeadiate 例如下面代码

image.png

如果都没有要执行的就会跳回到poll判断等待,因为代码是从上往下执行,如果check里的时间先到就会执行了,如果想让上面代码固定可控顺序需要修改

image.png 先优先调用setimmediate

image.png

image.png

特殊的2个 nextTick 微任务promise nextTick 早于 promise

image.png

代码例子

console.log("同步脚本开始");
  setTimeout(() => {
    console.log("timer定时器-0秒");
  }, 0);
  // fs.readFile("a.text", "utf-8", (err, data) => {
  //   console.log("readFile====io-poll阶段", data);
  // });
  setImmediate(() => {
    console.log("setImmediate");
  });
  // process.nextTick(() => {
  //   console.log("nextTick");
  // });
  Promise.resolve().then(() => {
    console.log("Promise");
  });
  console.log("同步脚本结束");
  
  
  这种情况下,setTimeout时间在0的情况下, check timer2个阶段的顺序不是固定的

image.png

image.png

image.png

来做一个更全复杂的代码

process.nextTick(function(){
    console.log('1');
});
process.nextTick(function(){
    console.log('2');
     setImmediate(function(){
        console.log('3');
    });
    process.nextTick(function(){
        console.log('4');
    });
});

setImmediate(function(){
    console.log('5');
     process.nextTick(function(){
        console.log('6');
    });
    setImmediate(function(){
        console.log('7');
    });
});

setTimeout(e=>{
    console.log(8);
    new Promise((resolve,reject)=>{
        console.log(8+'promise');
        resolve();
    }).then(e=>{
        console.log(8+'promise+then');
    })
},0)

setTimeout(e=>{ console.log(9); },0)

setImmediate(function(){
    console.log('10');
    process.nextTick(function(){
        console.log('11');
    });
    process.nextTick(function(){
        console.log('12');
    });
    setImmediate(function(){
        console.log('13');
    });
});

console.log('14');
 new Promise((resolve,reject)=>{
    console.log(15);
    resolve();
}).then(e=>{
    console.log(16);
})

注意几点
1,同步代码先执行 new promise里也是同步代码
2,process.nextTick在异步事件里优先级最高先执行--》下来是同级的所产生的微任务
3,当执行到的阶段所产生的then 微任务也是都执行完

以上个人理解,如果有问题欢迎大佬帮忙指出来

执行顺序是 从上到下 nextTick -》微任务 promise ->然后到事件循环(timer poll(这里处理I/O文件操作,所有操作完会回到这里等待) check)

推荐博文 www.ruanyifeng.com/blog/2018/0…