【Node.js】Node的事件循环,setTimeout()和setImmediate的执行顺序

首先让我们先看一下Node的时间循环阶段,完整的事件循环Tick是分成多个阶段的:

Node的事件循环阶段

  • 定时器:本阶段执行已经被setTimeout()和setInterval()的调度回调函数
  • 待定回调(I/O callback):对某些系统操作执行回调,比如TCP连接时接收到ECONNREFUSED
  • idle,prepare:仅系统内部使用
  • 轮询(poll):检索新的I/O事件,执行与I/O相关的回调
  • 检测:setImmediate()回调函数在这里执行
  • 关闭的回调函数:一些关闭的回调函数,如:socket.on(’close’,…)

事件循环中setTimeout()和setImmediate的执行顺序

setTimeout(() => {
  console.log('setTimeout')
}, 0)

setImmediate(() => {
  console.log('setImmediate')
})
  • 在node中,setTimeout(demo,0)===setTimeout(demo,1)
  • 在浏览器中setTimeout(demo,0)===setTimeout(demo,4)
  • 因为event loop的启动也是需要时间的,可能执行到poll阶段已经超过1ms,此时setTimeout就先执行。反之setImmediate先执行

出现这种情况的原因

  • 在node的源码中deps/uv/timer.c的地141行中,有一个uv_next_timeout的函数
  • 这个函数决定了poll阶段要不要阻塞在这里
  • 阻塞在这里的目的是当有异步IO被处理时,尽可能快的让代码被执行
  • 所以就会出现两种情况
    • 情况一:如果时间循环开启的时间是小于setTimeout函数的执行时间的;
      • 就意味着先开启了event-loop,但是这个时候执行到timer阶段,并没有定时器的回调被放到timer queue中;所以没有被执行,后续开启定时器和检测到有setImmediate时,就会跳过poll阶段,向后继续执行;这个时候是想检测setImmediate,第二次tick中执行timer中的setTimeout
    • 情况二:如果时间循环开启的时间是大于setTimmeout函数的执行时间的;
      • 这就意味着在第一次tick中,已经准备好timer queue;所以会直接按照顺序执行即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值