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

本文详细解析了Node.js中setTimeout和setImmediate在事件循环中的执行顺序,探讨了时间循环与定时器调度的关系,以及uv_next_timeout函数在其中的作用。特别关注了两种情况下它们的执行差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先让我们先看一下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;所以会直接按照顺序执行即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值