繁体   English   中英

始终在node.js中运行函数

[英]running a function all the time in node.js

为了始终有一个函数的单个实例一直运行,在某种情况下以下方法会出现问题吗?

const Q = require('q');

(function main() {
        Q.fcall(somePromiseFunction).then(_ => {
                main();
        });
})();

我想知道一段时间后递归内存堆栈是否会溢出并且程序是否终止?

令人惊讶的是,不! 我相信您的代码应该可以正常运行。

JavaScript中的异步操作(例如setTimeout()XMLHttpRequestPromise利用称为事件循环事件在程序的正常流程之外执行。 实际上,当异步发生时,它会添加到“队列”(与堆栈完全分离)中。 堆栈清空后,事件循环将开始处理这些排队的消息,并逐一执行它们的关联功能。

JavaScript中几乎所有异步的东西都是以这种方式工作的,其中包括Q promises库。 因此,在您的示例中,这是(非常)简化的解释:

  • main()被调用,创建一个新的堆栈框架。
  • Q.fcall(somePromiseFunction)被调用时,创建第二堆栈帧(并且假定第三,当somePromiseFunction被调用。该衬托异步操作的背景下,与通过了功能then设置为回调。
  • Q.fcall(somePromiseFunction)现在已经返回,因此那些堆栈帧被清除了。
  • main()也已到达末尾,因此也被清除了-我们回到了一个空堆栈。
  • 一旦异步操作完成时,一个消息被压入事件队列,你then与之相关联的回调。
  • 堆栈为空,因此事件循环开始处理。
  • 您的回调被执行。

这里要注意的重要一点是您的代码不会递归 您的then回调只会从事件队列中调用,而不会通过main()进行调用,因此堆栈可以在两次迭代之间清除而不会出现问题。

我建议您观看演讲“无论如何,事件循环到底是什么?” 有关这一切如何工作的更多信息-他们的解释方式是让它最终对我点击的原因。

编辑:为了回应您在评论中的问题,我将澄清一些事情。 最简单形式的递归函数如下所示:

function recursive() {
    recursive();
}

调用一个函数会分配一个堆栈帧,该堆栈帧在返回时会清除。 但是,如果没有某种打破循环的方式,那么像这样的递归函数将永远不会返回-它只会继续运行,不断分配堆栈帧,直到出现堆栈溢出错误为止。 但这并不意味着您永远不要在JavaScript中使用递归-有时它会很有用! 但是您需要注意,如果递归太多而又没有返回,那么您将到达堆栈的顶部。

在回答您的另一个问题时-事件循环/您的回调不特别等待main()结束,它仅等待堆栈清除。 这是堆栈在程序中的作用的简化可视化:

[]
[main]
[main, fcall]
[main, fcall, somePromiseFunction]
[main, fcall]
[main]
[main, then]
[main]
[]                                 // Main returned, so the stack is clear
[yourCallback]                     // The event loop kicks in, runs your callback
[yourCallback, main]
...                                // Above steps repeat
[yourCallback]                     // Main returned
[]                                 // Stack clears, so the event loop kicks in again

将此与我不断重复的功能进行比较:

[]
[recursive]
[recursive, recursive]            // Nothing stops the recursion,
[recursive, recursive, recursive] // so the stack is never going to clear!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM