NodeJs中的事件循环

在上期发表的博客中,我们详细讲述了一下JavaScript中的事件循环,我突然又想起来,NodeJS也是基于JavaScript语言的一种后台语言。那么他的事件循环跟Javascript中的事件循环有什么相同点又要什么区别呢?今天我们带着这样的疑问也来看看nodejs中的事件循环吧!

1.事件循环 

如上图,大概就是nodejs中的事件循环基本流程。在进入后判断代码是否都为同步代码,如果都为同步代码,则不进入事件循环,直接结束。如果有异步代码,会进入相应的流程队列中。现在就让我们来介绍一下NodeJs中的几种主要的队列的功能和作用吧!

1. 1  timers队列

timers队列是存放计时器的回调函数队列,如setTimeout和setIterval都会进入这个队列。等到计时器时间到达之后,会在poll队列中执行回调(注意,setImmediate不进入timers队列!

1.2  poll轮询队列

除了timers、checks,绝大部分回调都会放入该队列,比如:文件的读取、监听用户请求等

如果poll中有回调,依次执行回调,直到清空队列。如果poll中没有回调,等待其他队列中出现回调,结束该阶段,进入下一阶段,如果其他队列也没有回调,持续等待,直到出现回调为止

1.3 check检查队列

使用setImmediate的回调会直接进入这个队列

1.4 nextTick 和 Promise

nextTick:队列中的超级VIP,在事件循环中,每次打算执行一个回调之前,如计时器到时间了,要执行计时器中的回调了,但是不能直接执行,要看看nextTick队列中有没有还没有执行完的回调,如果有就先把nextTick中的执行完了,知道里面没有东西可以执行了,再来执行其他的回调。举个通俗点的例子,就比如你去银行取钱,但是那个银行只有一个窗口。银行有金卡VIP用户,普通用户必须等金卡用户们都取走钱之后,他才能去取钱,不然是取不到钱的。如果有新的VIP用户来,普通用户就必须还得等着,直到VIP金卡用户取完了,实在没有了。再去取钱。

Promise:跟nextTick一样,队列中的VIP,只是优先级没有nextTick高。这里就不多做重述了。

2.实际案例

   2.1demo1

const fs = require("fs");
fs.readFile("./index.js", () => {
  setTimeout(() => console.log(1), 0);
  setImmediate(() => console.log(2));
});

在上面这个简单案例中,先来看看有没有同步代码,只有一个readFlie读取,直接看内部,有一个setTimeout计时器和一个setImmediate,这两个都是异步操作,直接进事件循环,上面我们讲过,setTimeout直接进入timers队列,而setImmediate比较特殊,他直接进入poll队列,等setTimeout到时之后,poll队列才会执行里面的回调。所以在这里setImmediate肯定比setTimeout先执行,所以先执行输出2,再执行输出1。让我们来看看结果吧!

2.2demo2

setImmediate(() => {
  console.log(1);
});

process.nextTick(() => {
  console.log(2);
  process.nextTick(() => {
    console.log(6);
  });
});

console.log(3);

Promise.resolve().then(() => {
  console.log(4);
  process.nextTick(() => {
    console.log(5);
  });
});

小伙伴们已经理解了第一个简单案例的话,那让我们来一个更加复杂一点的案例来看看吧!让我们一起来分析分析,答案不就是呼之欲出吗。

首先在代码块中寻找同步代码,我们看到只有一个输出3是同步的。所以我们主线程先输出3是毫无疑问的。再来看异步代码。我们上面说过nextTick是事件循环中的超级VIP,所以先看nextTick,在nextTick里又分了同步和一个nextTick队列,所以当然先输出2,再输出6。这个nextTick代码块执行完成之后,再来看,我们说过Promise是事件循环中的VIP,等到nextTick执行完之后,就看他了。所以我们来看Promise代码块。里面又分了同步输出4和nextTick输出5,所以毫无疑问先输出4再输出5。最后还剩一个setImmediate,等到nextTick和Promise里面的东西都执行完之后,终于他才能执行了。所以我们的答案应该是326451。让我们来看看输出结果跟我们分析的一不一致吧!

太棒了!答案完全一致!如果大家分析这题没有问题的话!那我们再来看看更复杂一点的吧!

3.demo3

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");

这里的分析和前面讲的一样,这里大家可以看看自己分析分析。

如果这道题可以分析正确的话,我相信大家对nodeJS中的事件循环已经有一个清楚的认知了!小伙伴们可以在评论区踊跃发言!如有不对,请及时纠正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值