【问题标题】:do we need process.exit(1) when we use promises in node.js在 node.js 中使用 Promise 时是否需要 process.exit(1)
【发布时间】:2014-10-24 17:33:14
【问题描述】:

在我们公司,我们正在讨论在使用 Promise 时是否需要在 node.js 中出现未处理的异常时退出进程

我脑子里一直在玩两种思想

  • 当我们在 node.js 中使用 Promise 时,我们需要使用 process.exit(1)

  • 我们在使用 Promise 时不需要使用 process.exit(1)

顺便说一下,我们计划将 blubird 模块用于承诺。

https://www.npmjs.org/package/bluebird

我想知道是否有必要在发生未处理的异常时退出进程,因为在使用 Promise 时,我们会得到“finally”语句来清理资源

http://canop.org/blog/?p=516

此外,当涉及到 node.js 时,promise 可能无法自行处理的错误类型(如果有的话,我们可能需要通过处理)

process.on("uncaughtException")
{
process.exit(1);
}

【问题讨论】:

  • 一行 - 不,你没有。承诺是安全的。这就像承诺的意义。您的代码获得了同步代码的理想属性,例如返回和抛出。
  • 请注意,您应该使用键入的捕获。特别是查看 OperationalError

标签: node.js promise bluebird


【解决方案1】:

简短的回答,不。

长答案:

当您调用process.exit() 时,您会导致处理停止。退出事件被触发,这是任何代码运行的最后机会,并且事件循环停止。此后不久,Node.js 实际上完全停止并返回指定的退出代码。因此 process.exit() 会阻止 Node.js 在此之后执行任何有形的操作,并且应用程序也会停止。

问题

问题是process.exit() 可以随时被应用程序的任何部分调用。没有什么能阻止解析器调用它:

exports.parse = function(text) {

    if (canParse(text)) {
        return doTheParse(text);
    } else {
        console.error("Can't parse the text.");
        process.exit(1);
    }

};

因此,如果文本可以被解析,那么它就是,否则会向控制台输出错误并调用 process.exit(1)。对于一个低级的解析器来说,这是一个非常大的责任。

由于任何模块都可以调用process.exit(),这意味着任何出错的函数调用都可能决定关闭应用程序。这不是一个好的状态。应用程序的一个区域应该决定何时以及是否调用process.exit() 以及退出代码应该是什么(通常是应用程序控制器)。公用事业等不应该使用process.exit(),这超出了他们的职责范围。

每当您考虑使用 process.exit() 时,请考虑抛出错误:

抛出错误与调用 process.exit() 具有类似的效果,因为此函数中的代码执行会立即停止。但是,调用函数有机会捕获错误并以优雅的方式响应它。如果调用堆栈上没有干预,则在进程上触发uncaughtException 事件。如果没有事件处理程序,那么 Node.js 将触发退出事件并以非零退出代码退出,就像调用 process.exit() 时一样;如果有事件处理程序,则由您手动调用 process.exit() 来指定要使用的退出代码。

关键是抛出错误让应用程序有机会捕获错误并从中恢复,这几乎总是处理模块代码时所期望的情况。

来源:here

【讨论】:

  • 任意代码可以调用 process.exit 并不意味着任意代码可以。通过相同的逻辑,代码可以格式化您的计算机或打开后门。 编辑对不起,我看错了,我们实际上是在争论同一点。
  • 另外值得一提的是,它与流行的看法不同。在每个错误上重新启动服务器并不是 Node 中可行的错误处理策略,它是 DOS 漏洞的快速路径。
  • @BenjaminGruenbaum Esailiza 关于一个有问题的模块的观点怎么样???
  • @BenjaminGruenbaum 拒绝连接到数据库是否严重到足以停止服务器的错误?您能否提出更好的方法来处理此错误或从中恢复?
  • @devoto13 如果数据库连接失败,那么您可以尝试重试连接它 - 就个人而言,我几乎总是在数据库前面有一个缓存,我可以继续为客户提供服务 - 事情是:重新启动服务器不太可能解决无法连接到数据库之类的问题。
【解决方案2】:

.finally 不太适合资源管理:

  • 可能会被遗忘,只有仔细审核才能找到被遗忘的清理方法
  • 它可以在更复杂的场景中巧妙地泄漏资源

这就是为什么 2.0 引入了using,几乎不可能忘记使用它,因为资源承诺实际上是一个只能与using 一起使用的处理器。

因此,如果您使用using 获取资源,则无需从其中发生的错误中重新开始。

请注意,这不包括库中的错误,如果您使用的库会泄漏资源,那么您需要重新启动进程。例如,对于https://github.com/joyent/node/issues/7697,您无能为力(除了 fork 节点并在核心中使用 Promise,因此这种事情是不可能的:D)。

【讨论】:

  • promise 中是否有一个全局错误回调,如果我想记录你提到的错误,我可以使用它
  • @Nav 我没有提到错误,而是使用回调的库中的错误
  • aah ...k...如何将它用于 mongodb 事务.. 承诺是否稳定?您之前可能遇到的任何错误,例如此线程中提到的错误debuggable.com/posts/…
  • @Nav 这不是你能做什么的问题,如果你正在使用的库中有错误,你唯一能做的就是使用另一个库,它是否与 你是否使用了承诺。
  • @Nav 这篇博文谈到了一些不同的事情——你的错误和泄漏,使用using可以完全消除
猜你喜欢
  • 2016-10-03
  • 2017-08-26
  • 2017-05-11
  • 2011-11-02
  • 2019-09-29
  • 1970-01-01
  • 2017-01-09
  • 2019-01-25
相关资源
最近更新 更多