node.js事件循环简单理解——定时器,process.nextTick()等

主要是setTimeout(另一个定时器setTimeInterval),setImmediate,还有process.nextTick(),执行顺序问题。从其中看node.js事件循环机制。

首先,先看一下node.js的事件循环机制。

或者可以,看看一下下面的详情的例子留个印象或疑惑,再看这里的内容。

官网的图:

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

第一阶段timer(定时器阶段——也就是这两个setTimeout和setInterval)

        1、开始计时

        2、执行定时器的回调(注意仅仅是定时器的回调,也就是定时器的回调仅仅在这执行,不在第四阶段

第二阶段,pending callbacks(系统阶段)理解有这个即可

第三阶段,idle,prepare(准备阶段)理解有这个即可

第四阶段,poll(轮询查询阶段)

        1、如果回调队列里有待执行的回调函数(回调队列有很多种事件的回调函数)

从回调队列里取出,同步执行,注意(第一阶段的那两个setTimeout和setInterval的回调不在这里执行),直到回调队列为空(除第一阶段那两个),或者到达系统最大限度(例如内存不允许)。

        2、如果回调队列为空(除定时器的回调,其会跳过)

                1)如果有设置过setImmediate,则进入下一check阶段来执行去回调。

                2)如果没有设置过,则在此阶段停留,等待回调函数插入回调队列。或者定时器到点了,则进入下一check阶段,循环回到第一阶段执行定时器的回调。

第五阶段,check(专门执行setImmediate回调)

第六阶段,close callback(关闭回调阶段)理解有这个即可

还有一个process.nextTick(),这是立即执行的函数。什么是立即执行的函数,也就是无论此时事件循环处于那一阶段,它都可以执行这个函数,且其优先级高,比其他回调先执行。其相当于是一个VIP,在任何阶段都可以执行且首先执行。

详细分析:

setTimeout(() => { console.log('setTimeout'); })
setImmediate(() => { console.log('setImmediate'); })

setTimeout(() => { console.log('setTimeout'); })相当于setTimeout(() => { console.log('setTimeout'); },0)。

        可以看到两次结果不一样,为什么两次执行结果会不一样呢?

        这是因为当处于第一阶段的时候,这个定时器会交个相应的定时器模块执行,不在主线程执行,有可能这个模块把相应的回调已经执行了放在了回调队列里,而此时事件循环还没有去到下一阶段,所以就随便执行了这个定时器回调。所以会先输出setTimeout。

        但也有可能当定时器模块把回调放到回调队列里时,事件循环已经到了下一阶段了,所以此时会先输出setImmediate。

        总的来说,这两个谁先,与事件循环的频率有关。

        上面是主线程没有内容执行,但如果主线程上有内容要执行,此时定时器模块肯定已经把回调放到了回调队列(因为其设置的定时是0ms),此时肯定会先在第一阶段上执行输出setTimeout。

如下:

setTimeout(() => { console.log('setTimeout'); })
setImmediate(() => { console.log('setImmediate'); })

console.log('主线程的输出');

        如果有,nextTick的话,它会在任何一个阶段都可以执行,且先执行(当然还是要先执行主线程的代码先):

setTimeout(() => { console.log('setTimeout'); })

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

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

console.log('主线程的输出');

官网总图:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值