I/O 回调中调度的 setImmediate() 函数能否重新计算其他 I/O 通知的超时时间?

问题描述

Node js 的事件循环有 poll 阶段。它的目的是阻塞等待 I/O 通知,然后执行所需的回调。在进入该阶段之前计算等待的超时时间。如果有通过 setImmediate 安排的操作,则超时设置为 0,如果定时器发生,则超时设置为查看它们,如果没有此类障碍,阻塞将“永远”继续。

如果超时最初设置为“无穷大”并且 I/O 回调使用 setImmediatesetInterval 调度函数,会发生什么?超时是立即重新计算还是仅在 I/O 队列为空后(在下一次循环迭代中)?

因此,如果我们等待两个启动的异步操作,回调 AB 并在收到 I/O 通知后执行 A 并依次安排一些 {{1} } 函数C 函数会先执行 setImmediate 还是 B

解决方法

请注意,对于一些具有定时器支持的更常见的异步 API(例如 select()kqueue() 系统调用),零定时器值 (0) 表示无穷大,因此您无法通过计算下一个超时值并调用异步 API 来以通常的方式实现 setImmediate()nextTick() 之类的函数。相反,所有 setImmediate()nextTick() 回调必须在调用异步 API 之前同步调用。

因此,由于 C 是对 setImmediate() 的回调,它将在我们重新进入事件循环以等待 B 触发之前被调用。

因此,如果 Aonly a 被触发,那么函数调用的顺序将是:AC

但如果 AB 同时发生,函数调用的顺序将是:ABC

注意我说的是 AC 而不是 A,C,B 因为我们没有说 B 被触发.据我所知,B 只会在 8 个月后触发,甚至永远不会触发。

但是如果 A 被触发并且 1 毫秒后 B 发生,那么函数调用的顺序将是:ACB>


是否有可能在同一个事件循环中发生两个事件?一般是的。如果是网络 I/O,则不太可能,因为 IP 数据包是序列化的,但它仍然可能发生,特别是如果您有一台带有多个网卡的机器。如果是像 DOM 更新这样的图形事件,那么在同一个事件循环中发生的两件事很常见,例如:页面调整大小和内容重排可以同时发生,尤其是在使用媒体查询的响应式 CSS 中,页面调整大小可以触发内容重排。>