Node.js:在退出之前,节点是否总是等待setTimeout()完成?

时间:2013-08-05 03:15:49

标签: node.js

考虑一下:

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(),但我在测试中发现设置超时似乎也有效。 (也就是说,如果内置的东西有效,为什么要打扰模块呢?)我猜这个的意义不大,但我只是好奇它是否被指定某个节点实际上会在退出之前等待所有超时完成,所以这样做我能感到安全。

6 个答案:

答案 0 :(得分:8)

通常,节点会在正常退出之前等待所有超时。调用process.exit()将在超时之前退出。

详细信息是libuv的一部分,但文档对此进行了模糊评论:

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

  

你可以调用ref()来显式请求定时器保持程序打开

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:1)

简单方法解决方案:

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

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

制作bat文件:

  1. 制作文字文件
  2. START cmd.exe /k "node abc.js"
  3. 保存
  4. 将其重命名为abc.bat
  5. 制作捷径或其他任何内容。
  6. 打开它将打开CommandLine并运行nodejs文件。
  7. 使用settimeout这是一个坏主意。

答案 3 :(得分:1)

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

一旦告诉节点侦听事件,就像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事件中,您可以在10秒后添加setTimeout退出:

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 :(得分:0)

奇怪的是当你打电话给process.exit()或者有一个未被捕获的例外时,正如Jim Schubert指出的那样。除此之外,节点将等待超时完成。

答案 5 :(得分:0)

Node确实记得定时器,但前提是它可以跟踪定时器。至少那是我的经历。

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

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

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