在 node.js 中长时间运行无穷大

use*_*873 0 loops node.js

不能理解一件事。在服务器上,我有一些以异步模式永远运行的进程。例如像这样:

function loginf() {
  console.log(1+1);
  process.nextTick(loginf);
}
loginf();
Run Code Online (Sandbox Code Playgroud)

它的 recusrion,据我所知,它必须导致堆栈溢出和(或)占用内存。如何在node.js中永久运行而没有内存泄漏?是否可以?

jfr*_*d00 5

如果您想重复执行某些操作,并且希望以友好的方式执行此操作,从而为服务器中的其他事件留下待处理的循环,那么通常的方法是使用setInterval().

setInterval(function() {
    console.log("called");
}, 1000);
Run Code Online (Sandbox Code Playgroud)

像您一样重复调用相同的函数process.nextTick()并不是真正的递归,也不会导致堆栈溢出,因为在事件队列下次调用该函数之前堆栈已完全展开。它完成当前的执行路径,然后调用您传递给的函数nextTick()

您对此类操作的选择是:

setInterval()
setTimeout()
setImmediate()
process.nextTick()
Run Code Online (Sandbox Code Playgroud)

所有三个选择都让当前执行线程在调用回调函数之前完成,因此没有堆栈构建。

setInterval()使用设置为将来某个时间的系统计时器,并允许在调用setInterval()回调之前处理当前在队列中或在计时器时间发生之前队列中的所有其他事件。setInterval()当建议调用回调之间的时间暂停时使用,并且您希望一次又一次地重复调用回调。

setTimeout()使用设置为将来某个时间的系统计时器,并允许在调用setTimeout()回调之前处理当前在队列中或在计时器时间发生之前队列中的所有其他事件。您可以setTimeout()重复使用(从每个回调设置另一个超时),尽管这通常setInterval()是设计的。 setTimeout()在 node.js 中不遵循浏览器所做的最小时间间隔,因此setTimeout(fn, 1)会很快被调用,尽管不如实现差异快setImmediate()process.nextTick()由于实现差异。

setImmediate()一旦当前在事件队列中的其他事件都得到服务,就会运行。因此,这对系统中的其他事件是“公平的”。请注意,这更有效,setTimeout(fn, 0);因为它不需要使用系统计时器,而是直接编码到事件子系统中。当您希望堆栈展开并且您希望队列中已有的其他事件首先得到处理,但您希望回调尽快运行时,请使用此选项。

process.nextTick()当前执行线程完成(并且堆栈展开)后立即运行,但在事件队列中当前的任何其他事件之前运行。这并不“公平”,如果您一遍又一遍地使用process.nextTick(),您将使系统无法处理其他类型的事件。它可以使用一次,以便在堆栈展开后尽快运行某些内容,但不应反复使用。

一些有用的参考资料:

setImmediate 与 nextTick

Node.js 是否强制 setTimeout 的最小延迟?

NodeJS - setTimeout(fn,0) 与 setImmediate(fn)

setImmediate vs process.nextTick vs setTimeout