【问题标题】:Node.js: Will node always wait for setTimeout() to complete before exiting?Node.js:节点会一直等待 setTimeout() 完成后再退出吗?
【发布时间】:2016-07-04 01:31:00
【问题描述】:

考虑:

node -e "setTimeout(function() {console.log('abc'); }, 2000);"

这实际上会在程序退出之前等待超时触发。

我基本上想知道这是否意味着节点打算在退出之前等待所有超时完成。

这是我的情况。我的客户有一个 node.js 服务器,他将从 Windows 中运行,并带有一个快捷方式图标。如果节点应用程序遇到异常情况,它通常会立即退出,没有足够的时间在控制台中查看错误是什么,这很糟糕。

我的方法是用 try catch 包裹整个程序,所以现在它看起来像这样:try { (function () { ... })(); } catch (e) { console.log("EXCEPTION CAUGHT:", e); },但当然这会导致程序立即退出。

因此,在这一点上,我想留出大约 10 秒的时间让用户在异常退出之前对其进行查看或截屏。

我想我应该只通过 npm 模块使用阻塞 sleep(),但我在测试中发现设置超时似乎也有效。 (即,如果内置的东西有效,为什么还要打扰一个模块?)我想这的意义并不大,但我只是好奇它是否被指定在某个地方,该节点实际上会在退出之前等待所有超时完成,所以这样做我可以感到安全。

【问题讨论】:

    标签: node.js


    【解决方案1】:

    一般来说,节点会在正常退出之前等待所有超时触发。调用process.exit() 将在超时前退出。

    详细信息是libuv 的一部分,但文档对此做出了含糊的评论:

    http://nodejs.org/api/all.html#all_ref

    您可以调用 ref() 显式请求计时器保持程序打开

    将所有事实放在一起,setTimeout 默认情况下旨在保持事件循环打开(因此,如果这是唯一未决的事情,程序将等待)。您可以以编程方式禁用或重新启用该行为。

    【讨论】:

    • +1,当我浏览文档的那部分时,我下意识地拒绝了一个名为 ref 的函数,因为它可能与 setTimeout 有任何关系。
    【解决方案2】:

    迟到的答案,但肯定是的 - Nodejs 将等待 setTimeout 完成 - 请参阅 this documentation。巧合的是,还有一种等待 setTimeout 的方法,那就是对从 setTimeoutsetInterval 返回的对象调用 unref

    总结一下:如果你想让 Nodejs 等到超时被调用,你不需要做任何事情。如果您希望 Nodejs 等待特定的超时,请在其上调用 unref

    【讨论】:

      【解决方案3】:

      如果节点没有等待所有 setTimeoutsetInterval 调用完成,您将无法在简单的脚本中使用它们。

      一旦你告诉 node 去监听一个事件,就像 setTimeout 或一些异步 I/O 调用一样,事件循环将循环直到它被告知退出。

      您可以绑定一个事件侦听器来处理,就像文档中的示例一样,而不是将所有内容包装在 try/catch 中:

      process.on('uncaughtException', function(err) {
        console.log('Caught exception: ' + err);
      });
      
      setTimeout(function() {
        console.log('This will still run.');
      }, 500);
      
      // Intentionally cause an exception, but don't catch it.
      nonexistentFunc();
      console.log('This will not run.');
      

      uncaughtException 事件中,您可以添加setTimeout 以在 10 秒后退出:

      process.on('uncaughtException', function(err) {
        console.log('Caught exception: ' + err);
        setTimeout(function(){ process.exit(1); }, 10000);
      });
      

      如果您可以从该异常中恢复,您可能需要查看域:http://nodejs.org/api/domain.html

      编辑:

      实际上可能还有另一个问题:您的客户端应用程序没有做足够的(或任何?)日志记录。您可以使用log4js-node 写入临时文件或某些特定于应用程序的位置。

      【讨论】:

        【解决方案4】:

        简单的解决方法:

        • 制作一个启动 nodejs 的批处理 (.bat) 文件
        • 用它做一个快捷方式

        为什么这是最好的。这样,您的客户端将在命令行中运行 nodejs。即使 nodejs 程序返回,命令行也不会发生任何事情。

        制作bat文件:

        1. 制作文本文件
        2. 输入START cmd.exe /k "node abc.js"
        3. 保存
        4. 将其重命名为 abc.bat
        5. 做一个快捷方式或其他什么。
        6. 打开它将打开命令行并运行 nodejs 文件。

        为此使用 settimeout 是个坏主意。

        【讨论】:

        • 谢谢,我是 Windows 的老用户,但不知道 .bat 文件对这类事情有何帮助。
        • 好吧,蝙蝠也会继续前进并立即退出。我想我可以使用 windows shell sleep 命令...
        • 把这个放到bat文件START cmd.exe /k "node abc.js"
        【解决方案5】:

        奇怪的是当您调用 process.exit() 或出现未捕获的异常时,正如 Jim Schubert 所指出的那样。除此之外,节点将等待超时完成。

        【讨论】:

          【解决方案6】:

          Node 确实记得计时器,但前提是它可以跟踪它们。至少这是我的经验。

          如果您在箭头/匿名函数中使用setTimeout,我建议您在数组中跟踪您的计时器,例如:

          => {
            timers.push(setTimeout(doThisLater, 2000));
          }
          

          并确保 let timers = []; 未设置在会消失的方法中,即全局。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-05-06
            • 2020-03-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多