为什么节点js在promise调用后不会退出

时间:2017-11-15 16:14:38

标签: node.js

在以下代码中:

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

sleep(10000);

为什么NodeJS不会立即退出?什么导致Promise等待?

我认为我需要await sleep(10000) - 但这会产生错误。

2 个答案:

答案 0 :(得分:4)

Nodejs在退出之前等待仍处于活动状态的计时器。您可以通过调用计时器对象本身上的.unref()来告诉它不要等待计时器。

所以,它实际上并不是它所等待的承诺,而是它正在等待的计时器。

在内部,node.js保留一个未被.unref()打开的定时器数量的引用计数,并且在该计数(以及其他内容)变为零之前不会退出。

以下是node.js doc for timers的一些摘录:

课程:超时

  

默认情况下,使用setTimeout()或setInterval()调度计时器时,只要计时器处于活动状态,Node.js事件循环就会继续运行。这些函数返回的每个Timeout对象都会导出timeout.ref()和timeout.unref()函数,这些函数可用于控制此默认行为。

<强> timeout.unref()

  

调用时,活动的Timeout对象不需要Node.js事件循环保持活动状态。如果没有其他活动保持事件循环运行,则进程可以在调用Timeout对象的回调之前退出。多次调用timeout.unref()将无效。

答案 1 :(得分:1)

查看节点中的计时器unref()函数 - https://nodejs.org/api/timers.html#timers_timeout_unref

  

调用时,活动的Timeout对象不需要Node.js事件循环保持活动状态。如果没有其他活动使事件循环继续运行,则该进程可以在调用Timeout对象的回调之前退出。

您可以创建超时并在其上调用unref()函数 - 这将阻止节点保持活动状态,如果它正在等待的唯一事情就是超时。

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms).unref();
    });
}

作为旁注,相同的unref功能也可用于setTimeout来电。

正如jfriend00正确指出的那样,不是保持节点活着的承诺,而是超时。