什么是一个Node.js事件循环打勾?

我已经进入了node.js体系结构的内部,而且我看到的一个术语是“tick”,就像在“event loop”的next tick或者nextTick()函数中一样 。

我没有看到什么是“滴答”的确切定义。 根据各种文章( 比如这篇文章),我已经能够将一个概念拼凑在脑海中,但是我不确定它有多精确。

我可以得到一个精确和详细的描述一个node.js事件循环打勾?

请记住,尽pipeJavaScript是单线程的,但是所有节点的I / O和对本机API的调用都是asynchronous的(使用平台特定的机制),或者在单独的线程上运行。 (这一切都是通过libuv处理的。)

因此,当套接字上有数据或者本机API函数已经返回时,我们需要一种同步的方式来调用对刚发生的特定事件感兴趣的JavaScript函数。

从本地事件发生的线程中调用JS函数是不安全的,这与在常规的multithreading应用程序中遇到的相同原因 – 竞争条件,非primefaces内存访问等等。

所以我们所做的就是以线程安全的方式将事件放在队列中。 在过分简化的伪代码中,类似于:

lock (queue) { queue.push(event); } 

然后,回到主要的JavaScript 线程 (但在C的一面),我们做的是这样的:

 while (true) { // this is the beginning of a tick lock (queue) { var tickEvents = copy(queue); // copy the current queue items into thread-local memory queue.empty(); // ..and empty out the shared queue } for (var i = 0; i < tickEvents.length; i++) { InvokeJSFunction(tickEvents[i]); } // this the end of the tick } 

while (true) (实际上并不存在于节点的源代码中;这纯粹是说明性的)表示事件循环 。 内部for调用队列中每个事件的JS函数。

这是一个滴答声:同步调用与任何外部事件关联的零个或多个callback函数。 一旦队列被清空并且最后一个函数返回,滴答就结束了。 我们回到开头(下一个勾号),并检查在JavaScript运行时从其他线程添加到队列中的事件。

什么可以添加到队列中的东西?

  • process.nextTick
  • setTimeout / setInterval
  • I / O(来自fsnet等等的东西)
  • crypto的处理器密集型function,如密码stream,pbkdf2和PRNG(实际上是一个例子…)
  • 任何使用libuv工作队列来使同步C / C ++库调用看起来asynchronous的本地模块