国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

詳細談?wù)凬odeJS進(jìn)程是如何退出的

發(fā)布時(shí)間:2021-08-17 12:16 來(lái)源: 閱讀:0 作者:眾里千尋 欄目: JavaScript 歡迎投稿:712375056

目錄

前言

有幾種因素可以導致 NodeJS 進(jìn)程退出。在這些因素中,有些是可預防的,比如代碼拋出了一個(gè)異常;有些是不可預防的,比如內存耗盡。process 這個(gè)全局變量是一個(gè) Event Emitter 實(shí)例,如果進(jìn)程優(yōu)雅退出,process 會(huì )派發(fā)一個(gè) exit 事件。應用代碼可以監聽(tīng)這個(gè)事件,來(lái)做最后的清理工作。

下面的表格列舉了可以導致進(jìn)程退出的因素。

主動(dòng)退出

process.exit(code) 是最直接的結束進(jìn)程的方法。code 參數是可選的,可以為 0 ~ 255 之間任何數字,默認為 0。0 表示進(jìn)程執行成功,非 0 數字表示進(jìn)程執行失敗。

當 process.exit() 被使用時(shí),控制臺不會(huì )有任何輸出,如果我們想在進(jìn)程推出的時(shí)候像控制臺輸出一些錯誤說(shuō)明信息,則需要在調用之前顯示的輸出錯誤信息。

node -e "process.exit(42)"
echo $?

上面的代碼直接退出了 NodeJS 進(jìn)程,命令行沒(méi)有任何輸出信息。用戶(hù)在遭遇進(jìn)程退出的時(shí)候,無(wú)法獲取有效的錯誤信息。

function checkConfig(config) {
  if (!config.host) {
    console.error("Configuration is missing 'host' parameter!");
    process.exit(1);
  }
}

在上面的代碼中,我們在進(jìn)程退出之前輸出的明確的錯誤信息。

process.exit() 的功能非常強大,但是我們不應該在工具庫中使用。如果在工具庫中遇到的錯誤,我們應該以異常的形式拋出,從而讓?xiě)么a決定如何處理這個(gè)錯誤。

Exceptions, Rejections 和 Emitted Errors

process.exit() 在應用啟動(dòng)配置檢查等場(chǎng)景中非常有用,但是在處理運行時(shí)異常時(shí),它并不適用,我們需要其他的工具。

比如當應用在處理一個(gè) HTTP 請求時(shí),一個(gè)錯誤不應該導致進(jìn)程終止,相反,我們應該返回一個(gè)含有錯誤信息的響應。

Error 類(lèi)可以包含描述錯誤發(fā)生的詳細信息的數據,比如調用堆棧和錯誤文本。通常我們會(huì )定義特定場(chǎng)景的 XXXError,這些 XXXError 都繼承制 Error 類(lèi)。

當我們使用 throw 關(guān)鍵字,或者代碼邏輯出錯時(shí),一個(gè)錯誤就會(huì )被拋出。此時(shí),系統調用棧會(huì )釋放,每個(gè)函數會(huì )退出,直到遇到一個(gè) 包裹了當前調用的 try/catch 語(yǔ)句。如果沒(méi)有 try/catch 語(yǔ)句,則這個(gè)錯誤會(huì )被認為是未捕獲的異常。

通常,在 NodeJS 應用中,我們會(huì )給 Error 類(lèi)定義一個(gè) code 屬性,作為用來(lái)描述具體錯誤的錯誤碼,這么做的優(yōu)點(diǎn)是可以使錯誤碼保持唯一,同時(shí)還能使得錯誤碼是可讀的。同時(shí),我們也可以配合 message 屬性來(lái)描述具體的錯誤信息。

當一個(gè)未捕獲的異常拋出時(shí),控制臺會(huì )打印調用堆棧,同時(shí)進(jìn)程退出,退出狀態(tài)碼為 1.

/tmp/foo.js:1
throw new TypeError('invalid foo');
^
Error: invalid foo
    at Object.<anonymous> (/tmp/foo.js:2:11)
    ... TRUNCATED ...
    at internal/main/run_main_module.js:17:47

這段控制臺輸出信息說(shuō)明,錯誤發(fā)生在 foo.js 中的第 2 行第 11 列。

全局變量 process 是個(gè) Event Emitter 實(shí)例,可以通過(guò)監聽(tīng) uncaughtException 事件來(lái)處理這些未捕獲異常。下面的代碼展示了如何使用:

const logger = require("./lib/logger.js");
process.on("uncaughtException", (error) => {
  logger.send("An uncaught exception has occured", error, () => {
    console.error(error);
    process.exit(1);
  });
});

Promise Rejection 與拋出異常類(lèi)似。我們可以通過(guò)調用 reject() 函數或者在 async 函數中拋出異常來(lái)是的 promise 到達 rejected 狀態(tài)。下面的兩段代碼功能是相似的。

Promise.reject(new Error("oh no"));

(async () => {
  throw new Error("oh no");
})();

目前,在 NodeJS 14 中,Promise Rejection 不會(huì )導致進(jìn)程退出,在后續的版本中,Promise Rejection 可能會(huì )導致進(jìn)程退出。

下面是一段未捕獲的 Promise Rejection 的控制臺輸出樣例。

(node:52298) UnhandledPromiseRejectionWarning: Error: oh no
    at Object.<anonymous> (/tmp/reject.js:1:16)
    ... TRUNCATED ...
    at internal/main/run_main_module.js:17:47
(node:52298) UnhandledPromiseRejectionWarning: Unhandled promise
  rejection. This error originated either by throwing inside of an
  async function without a catch block, or by rejecting a promise
  which was not handled with .catch().

我們可以通過(guò)監聽(tīng) unhandledRejection 事件來(lái)處理未捕獲的 Rejection. 樣例代碼如下:

process.on("unhandledRejection", (reason, promise) => {});

Event Emitter 是 NodeJS 中的基礎模塊,應用廣泛。當 Event Emitter 的 error 事件未被處理時(shí),Event Emitter 就會(huì )拋出一個(gè)錯誤,同時(shí)會(huì )導致進(jìn)程退出。下面是一個(gè) Event Emitter error 的控制臺輸出。

events.js:306
    throw err; // Unhandled 'error' event
    ^
Error [ERR_UNHANDLED_ERROR]: Unhandled error. (undefined)
    at EventEmitter.emit (events.js:304:17)
    at Object.<anonymous> (/tmp/foo.js:1:40)
    ... TRUNCATED ...
    at internal/main/run_main_module.js:17:47 {
  code: 'ERR_UNHANDLED_ERROR',
  context: undefined
}

因此,我們在使用 Event Emitter 的時(shí)候,要確保監聽(tīng)了 error 事件,這樣在發(fā)生錯誤的時(shí)候,可以使得應用能夠處理這些錯誤,避免奔潰。

信號

信號是操作信息提供了進(jìn)程間通信機制。信號通常是一個(gè)數字,同時(shí)也可以使用一個(gè)字符串來(lái)標識。比如 SIGKILL 標識數字 9。不同的操作系統對信號的定義不同。下面表格里羅列的是基本通用的信號定義。

這表格里,是否可處理表示這個(gè)信號是否可被進(jìn)程接收并被處理。NodeJS 默認行為表示進(jìn)程在接收到這個(gè)信號以后默認執行的動(dòng)作。

我們可以通過(guò)如下方式來(lái)監聽(tīng)這些信號。

#!/usr/bin/env node
console.log(`Process ID: ${process.pid}`);
process.on("SIGHUP", () => console.log("Received: SIGHUP"));
process.on("SIGINT", () => console.log("Received: SIGINT"));
setTimeout(() => {}, 5 * 60 * 1000); // keep process alive

在一個(gè)命令行窗口中運行這段代碼,然后按下 Ctrl + C,此時(shí)進(jìn)程不會(huì )退出,而是會(huì )在控制臺打印一行接收到了 SIGINT 信號的日志信息。新起一個(gè)命令行窗口,執行如下命令,PROCESS_ID 為上面程序輸出的進(jìn)程 ID。

kill -s SIGHUP <PROCESS_ID>

通過(guò)新起的命令行,我們向原來(lái)的那個(gè)程序進(jìn)程發(fā)送了一個(gè) SIGHUP 信號,原來(lái)的命令行窗口中會(huì )打印一行接收到了 SIGHUP 信號的日志信息。

在 NodeJS 代碼中,進(jìn)程也可以給其他進(jìn)程發(fā)送信號。比如:

node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"

這段代碼同樣會(huì )在第一個(gè)命令行窗口中輸出一行接收到了 SIGHUP 信號的日志。

如果我們要讓第一個(gè)命令行窗口的進(jìn)程退出,則可以通過(guò)下面的命令來(lái)實(shí)現。

kill -9 <PROCESS_ID>

在 NodeJS 中,信號通常被用作控制進(jìn)程優(yōu)雅的退出。比如,在 Kubernetes 中,當一個(gè) pod 要退出時(shí),k8s 會(huì )像 pod 內的進(jìn)程發(fā)送一個(gè) SIGTERM 的信號,同時(shí)啟動(dòng)一個(gè) 30 秒的定時(shí)器。應用程序有 30 秒的時(shí)間來(lái)關(guān)閉連接、保存數據等。如果 30 秒之后進(jìn)程依然存活,k8s 會(huì )再發(fā)送一個(gè) SIGKILL 來(lái)強制關(guān)閉進(jìn)程。

小結

本文講述了可以導致進(jìn)程退出的幾種因素,分別是:

  • 主動(dòng)退出
  • 未捕獲的異常、未處理的 promise rejection、未處理的 Event Emitter error 事件
  • 系統信號

到此這篇關(guān)于NodeJS進(jìn)程是如何退出的文章就介紹到這了,更多相關(guān)NodeJS進(jìn)程退出內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

寡妇张开腿让黑人捅爽| 亚洲婷婷五月综合狠狠爱| 欧美另类人妻制服丝袜| 久久精品麻豆日日躁夜夜躁| 麻豆网神马久久人鬼片| 欧美精品一区二区精品久久|