本文摘自PHP中文网,作者青灯夜游,侵删。
本篇文章给大家介绍一下主动触发Node进程终止的一些方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。有几个原因会导致 Node.js 进程终止。其中一些是可以避免的,例如抛出错误时,而另一些是无法防止的,例如内存不足。全局 process
是一个 Event Emitter 实例,当执行正常退出时,将发出一个 exit
事件。然后程序代码可以通过侦听这个事件来执行最后的同步清理工作。
相关推荐:《nodejs 教程》
下面是可以主动触发进程终止的一些方法:
操作 | 例子 |
---|---|
手动流程退出 | process.exit(1) |
未捕获的异常 | throw new Error() |
未兑现的 promise | Promise.reject() |
忽略的错误事件 | EventEmitter#emit('error') |
未处理的信号 | $ kill <PROCESS_ID> |
其中有许多是属于偶然被触发的,例如未捕获的错误或未处理的 promise,但是其中也有为了直接使进程终止而创建的。
进程退出
使用 process.exit(code)
来终止进程是最直接的方法。这在当你知道自己的过程已经到了生命周期的尽头时非常有用。 code
值是可选的,默认值为0,最大可以设为 255。0 表示进程运行成功,而任何非零的数字都表示发生了问题。这些值可以被许多不同的外部工具使用。例如当测试套件运行时,非零值表示测试失败。
直接调用 process.exit()
时,不会向控制台写入任何隐式文本。如果你编写了以错误表示形式调用此方法的代码,则你的代码应该用户输出错误来帮助他们解决问题。例如运行以下代码:
1 2 |
|
在这种情况下,单行的 Node.js 程序不会输出任何信息,尽管 shell 程序确实会打印退出状态。遇到这样的进程退出,用户将无法理解究竟发生了什么事情。所以要参考下面这段程序配置错误时会执行的代码:
1 2 3 4 5 6 |
|
在这种情况下,用户没会很清楚发生了什么。他们运行这个程序,将错误输出到控制台上,并且他们能够纠正这个问题。
process.exit()
方法非常强大。尽管它在程序代码中有自己的用途,但实际上绝对不应该将其引入可重用的库中。如果在库中确实发生了错误,则应抛出这个错误,以便程序可以决定应该如何处理它。
exceprion、rejection 和发出的 Error
虽然 process.exit()
很有用,但对于运行时错误,你需要使用其他工具。例如当程序正在处理 HTTP 请求时,一般来说错误不应该终止进程,而是仅返回错误响应。发生错误的位置信息也很有用,这正是应该抛出 Error
对象的地方。
Error
类的实例包含对导致错误的原因有用的元数据,例如栈跟踪信息和消息字符串。从 Error
扩展你自己的错误类是很常见的操作。单独实例化 Error
不会有太多副作用,如果发生错误则必须抛出。
在使用 throw
关键字或发生某些逻辑错误时,将引发 Error
。发生这种情况时,当前栈将会“展开”,这意味着每个函数都会退出,直到一个调用函数将调用包装在 try/catch
语句中为止。遇到此语句后,将调用 catch
分支。如果错误没有被包含在 try/catch
中,则该错误被视为未捕获。
虽然你应该使用带有 Error
的 throw
关键字,例如 throw new Error('foo')
,但从技术上讲,你可以抛出任何东西。一旦抛出了什么东西,它就被认为是一个例外。抛出 Error
实例非常重要,因为捕获这些错误的代码很可能会期望得到错误属性。
Node.js 内部库中常用的另一种模式是提供一个 .code
属性,该属性是一个字符串值,在发行版之间应保持一致。比如错误的 .code
值是 ERR_INVALID_URI
,即使是供人类可读的 .message
属性可能会更改,但这个 code
值也不应被更改。
可悲的是,一种更常用的区分错误的模式是检查 .message
属性,这个属性通常是动态的,因为可能回需要修改拼写错误。这种方法是很冒险的,也是容易出错的。 Node.js 生态中没有完美的解决方案来区分所有库中的错误。
当引发未捕获的错误时,控制台中将打印栈跟踪信息,并且进程将回以退出状态 1 终止。这是此类异常的例子:
1 2 3 4 5 6 7 |
|
上面的栈跟踪片段表明错误发生在名为 foo.js
的文件的第 2 行第 11 列。
全局的 process
是一个事件发射器,可以通过侦听 uncaughtException
事件来拦截未捕获的错误。下面是一个使用它的例子,在退出前拦截错误以发送异步消息:
1 2 3 4 5 6 7 |
|
Promise 拒绝与抛出错误非常相似。如果 Promise 中的 reject()
方法被调用,或者在异步函数中引发了错误,则 Promise 可以拒绝。在这方面,以下两个例子大致相同:
1 2 3 4 5 |
|
这是输出到控制台的消息:
1 2 3 4 5 6 7 8 |
|
与未捕获的异常不同,从 Node.js v14 开始,这些 rejection 不会使进程崩溃。在未来的 Node.js 版本中,会使当前进程崩溃。当这些未处理的 rejection 发生时,你还可以拦截事件,侦听 process
对象上的另一个事件:
1 |
|
事件发射器是 Node.js 中的常见模式,许多对象实例都从这个基类扩展而来,并在库和程序中使用。它们非常欢迎,值得和 error 与 rejection 放在一起讨论。
相关阅读 >>
更多相关阅读请进入《前端》频道 >>
Vue.js 设计与实现 基于Vue.js 3 深入解析Vue.js 设计细节
本书对 Vue.js 3 技术细节的分析非常可靠,对于需要深入理解 Vue.js 3 的用户会有很大的帮助。——尤雨溪,Vue.js作者