這篇文章主要介紹了如何主動(dòng)終止Node.js進(jìn)程,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
成都創(chuàng)新互聯(lián)公司是一家專業(yè)提供市中企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、H5高端網(wǎng)站建設(shè)、小程序制作等業(yè)務(wù)。10年已為市中眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
1、能夠嵌入動(dòng)態(tài)文本于HTML頁(yè)面。2、對(duì)瀏覽器事件做出響應(yīng)。3、讀寫HTML元素。4、在數(shù)據(jù)被提交到服務(wù)器之前驗(yàn)證數(shù)據(jù)。5、檢測(cè)訪客的瀏覽器信息。6、控制cookies,包括創(chuàng)建和修改等。7、基于Node.js技術(shù)進(jìn)行服務(wù)器端編程。
有幾個(gè)原因會(huì)導(dǎo)致 Node.js 進(jìn)程終止。其中一些是可以避免的,例如拋出錯(cuò)誤時(shí),而另一些是無(wú)法防止的,例如內(nèi)存不足。全局 process
是一個(gè) Event Emitter 實(shí)例,當(dāng)執(zhí)行正常退出時(shí),將發(fā)出一個(gè) exit
事件。然后程序代碼可以通過(guò)偵聽這個(gè)事件來(lái)執(zhí)行最后的同步清理工作。
下面是可以主動(dòng)觸發(fā)進(jìn)程終止的一些方法:
操作 | 例子 |
---|---|
手動(dòng)流程退出 | process.exit(1) |
未捕獲的異常 | throw new Error() |
未兌現(xiàn)的 promise | Promise.reject() |
忽略的錯(cuò)誤事件 | EventEmitter#emit('error') |
未處理的信號(hào) | $ kill <PROCESS_ID> |
其中有許多是屬于偶然被觸發(fā)的,例如未捕獲的錯(cuò)誤或未處理的 promise,但是其中也有為了直接使進(jìn)程終止而創(chuàng)建的。
使用 process.exit(code)
來(lái)終止進(jìn)程是最直接的方法。這在當(dāng)你知道自己的過(guò)程已經(jīng)到了生命周期的盡頭時(shí)非常有用。 code
值是可選的,默認(rèn)值為0,最大可以設(shè)為 255。0 表示進(jìn)程運(yùn)行成功,而任何非零的數(shù)字都表示發(fā)生了問(wèn)題。這些值可以被許多不同的外部工具使用。例如當(dāng)測(cè)試套件運(yùn)行時(shí),非零值表示測(cè)試失敗。
直接調(diào)用 process.exit()
時(shí),不會(huì)向控制臺(tái)寫入任何隱式文本。如果你編寫了以錯(cuò)誤表示形式調(diào)用此方法的代碼,則你的代碼應(yīng)該用戶輸出錯(cuò)誤來(lái)幫助他們解決問(wèn)題。例如運(yùn)行以下代碼:
$ node -e "process.exit(42)" $ echo $?
在這種情況下,單行的 Node.js 程序不會(huì)輸出任何信息,盡管 shell 程序確實(shí)會(huì)打印退出狀態(tài)。遇到這樣的進(jìn)程退出,用戶將無(wú)法理解究竟發(fā)生了什么事情。所以要參考下面這段程序配置錯(cuò)誤時(shí)會(huì)執(zhí)行的代碼:
function checkConfig(config) { if (!config.host) { console.error("Configuration is missing 'host' parameter!"); process.exit(1); } }
在這種情況下,用戶沒(méi)會(huì)很清楚發(fā)生了什么。他們運(yùn)行這個(gè)程序,將錯(cuò)誤輸出到控制臺(tái)上,并且他們能夠糾正這個(gè)問(wèn)題。
process.exit()
方法非常強(qiáng)大。盡管它在程序代碼中有自己的用途,但實(shí)際上絕對(duì)不應(yīng)該將其引入可重用的庫(kù)中。如果在庫(kù)中確實(shí)發(fā)生了錯(cuò)誤,則應(yīng)拋出這個(gè)錯(cuò)誤,以便程序可以決定應(yīng)該如何處理它。
雖然 process.exit()
很有用,但對(duì)于運(yùn)行時(shí)錯(cuò)誤,你需要使用其他工具。例如當(dāng)程序正在處理 HTTP 請(qǐng)求時(shí),一般來(lái)說(shuō)錯(cuò)誤不應(yīng)該終止進(jìn)程,而是僅返回錯(cuò)誤響應(yīng)。發(fā)生錯(cuò)誤的位置信息也很有用,這正是應(yīng)該拋出 Error
對(duì)象的地方。
Error
類的實(shí)例包含對(duì)導(dǎo)致錯(cuò)誤的原因有用的元數(shù)據(jù),例如棧跟蹤信息和消息字符串。從 Error
擴(kuò)展你自己的錯(cuò)誤類是很常見的操作。單獨(dú)實(shí)例化 Error
不會(huì)有太多副作用,如果發(fā)生錯(cuò)誤則必須拋出。
在使用 throw
關(guān)鍵字或發(fā)生某些邏輯錯(cuò)誤時(shí),將引發(fā) Error
。發(fā)生這種情況時(shí),當(dāng)前棧將會(huì)“展開”,這意味著每個(gè)函數(shù)都會(huì)退出,直到一個(gè)調(diào)用函數(shù)將調(diào)用包裝在 try/catch
語(yǔ)句中為止。遇到此語(yǔ)句后,將調(diào)用 catch
分支。如果錯(cuò)誤沒(méi)有被包含在 try/catch
中,則該錯(cuò)誤被視為未捕獲。
雖然你應(yīng)該使用帶有 Error
的 throw
關(guān)鍵字,例如 throw new Error('foo')
,但從技術(shù)上講,你可以拋出任何東西。一旦拋出了什么東西,它就被認(rèn)為是一個(gè)例外。拋出 Error
實(shí)例非常重要,因?yàn)椴东@這些錯(cuò)誤的代碼很可能會(huì)期望得到錯(cuò)誤屬性。
Node.js 內(nèi)部庫(kù)中常用的另一種模式是提供一個(gè) .code
屬性,該屬性是一個(gè)字符串值,在發(fā)行版之間應(yīng)保持一致。比如錯(cuò)誤的 .code
值是 ERR_INVALID_URI
,即使是供人類可讀的 .message
屬性可能會(huì)更改,但這個(gè) code
值也不應(yīng)被更改。
可悲的是,一種更常用的區(qū)分錯(cuò)誤的模式是檢查 .message
屬性,這個(gè)屬性通常是動(dòng)態(tài)的,因?yàn)榭赡芑匦枰薷钠磳戝e(cuò)誤。這種方法是很冒險(xiǎn)的,也是容易出錯(cuò)的。 Node.js 生態(tài)中沒(méi)有完美的解決方案來(lái)區(qū)分所有庫(kù)中的錯(cuò)誤。
當(dāng)引發(fā)未捕獲的錯(cuò)誤時(shí),控制臺(tái)中將打印棧跟蹤信息,并且進(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
上面的棧跟蹤片段表明錯(cuò)誤發(fā)生在名為 foo.js
的文件的第 2 行第 11 列。
全局的 process
是一個(gè)事件發(fā)射器,可以通過(guò)偵聽 uncaughtException
事件來(lái)攔截未捕獲的錯(cuò)誤。下面是一個(gè)使用它的例子,在退出前攔截錯(cuò)誤以發(fā)送異步消息:
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 拒絕與拋出錯(cuò)誤非常相似。如果 Promise 中的 reject()
方法被調(diào)用,或者在異步函數(shù)中引發(fā)了錯(cuò)誤,則 Promise 可以拒絕。在這方面,以下兩個(gè)例子大致相同:
Promise.reject(new Error('oh no')); (async () => { throw new Error('oh no'); })();
這是輸出到控制臺(tái)的消息:
(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().
與未捕獲的異常不同,從 Node.js v14 開始,這些 rejection 不會(huì)使進(jìn)程崩潰。在未來(lái)的 Node.js 版本中,會(huì)使當(dāng)前進(jìn)程崩潰。當(dāng)這些未處理的 rejection 發(fā)生時(shí),你還可以攔截事件,偵聽 process
對(duì)象上的另一個(gè)事件:
process.on('unhandledRejection', (reason, promise) => {});
事件發(fā)射器是 Node.js 中的常見模式,許多對(duì)象實(shí)例都從這個(gè)基類擴(kuò)展而來(lái),并在庫(kù)和程序中使用。它們非常歡迎,值得和 error 與 rejection 放在一起討論。
當(dāng)事件發(fā)射器發(fā)出沒(méi)有偵聽器的 error
事件時(shí),將會(huì)拋出所發(fā)出的參數(shù)。然后將拋出出一個(gè)錯(cuò)誤并導(dǎo)致進(jìn)程退出:
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 }
確保在你使用的事件發(fā)射器實(shí)例中偵聽 error
事件,以便你的程序可以正常處理事件而不會(huì)崩潰。
信號(hào)是操作系統(tǒng)提供的機(jī)制,用于把用數(shù)字表示的消息從一個(gè)程序發(fā)送到另一個(gè)程序。這些數(shù)字通常用等價(jià)的常量字符串來(lái)表示。例如,信號(hào) SIGKILL
代表數(shù)字信號(hào) 9。信號(hào)可以有不同的用途,但通常用于終止程序。
不同的操作系統(tǒng)可以定義不同的信號(hào),但是下面列表中的信號(hào)一般是通用的:
名稱 | 編號(hào) | 可處理 | Node.js 默認(rèn) | 信號(hào)用途 |
---|---|---|---|---|
SIGHUP | 1 | 是 | 終止 | 父終端已關(guān)閉 |
SIGINT | 2 | 是 | 終止 | 終端試圖中斷,按下 Ctrl + C |
SIGQUIT | 3 | 是 | 終止 | 終端試圖退出,按下 Ctrl + D |
SIGKILL | 9 | 否 | 終止 | 進(jìn)程被強(qiáng)行殺死 |
SIGUSR1 | 10 | 是 | 啟動(dòng)調(diào)試器 | 用戶定義的信號(hào)1 |
SIGUSR2 | 12 | 是 | 終止 | 用戶定義的信號(hào)2 |
SIGTERM | 12 | 是 | 終止 | 代表優(yōu)雅的終止 |
SIGSTOP | 19 | 否 | 終止 | 進(jìn)程被強(qiáng)行停止 |
如果程序可以選擇實(shí)現(xiàn)信號(hào)處理程序,則 Handleable 一列則為是。為否的兩個(gè)信號(hào)無(wú)法處理。 Node.js 默認(rèn) 這一列告訴你在收到信號(hào)時(shí),Node.js 程序的默認(rèn)操作是什么。最后一個(gè)信號(hào)用途指出了信號(hào)對(duì)應(yīng)的作用。
在 Node.js 程序中處理這些信號(hào)可以通過(guò)偵聽 process
對(duì)象上的更多事件來(lái)完成:
#!/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
在終端窗口中運(yùn)行這個(gè)程序,然后按 Ctrl + C
,這個(gè)進(jìn)程不會(huì)被終止。它將會(huì)聲明已接收到 SIGINT
信號(hào)。切換到另一個(gè)終端窗口,并根據(jù)輸出的進(jìn)程 ID 值執(zhí)行以下命令:
$ kill -s SIGHUP <PROCESS_ID>
這演示了一個(gè)程序怎樣向另一個(gè)程序發(fā)送信號(hào),并且在第一個(gè)終端中運(yùn)行的 Node.js 程序中輸出它所接收到的 SIGHUP
信號(hào)。
你可能已經(jīng)猜到了,Node.js 也能把命令發(fā)送到其他程序??梢杂孟旅娴拿钜园研盘?hào)從臨時(shí)的 Node.js 進(jìn)程發(fā)送到你現(xiàn)有的進(jìn)程:
$ node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"
這還會(huì)在你的第一個(gè)程序中顯示 SIGHUP
消息。現(xiàn)在,如果你想終止第一個(gè)進(jìn)程,要運(yùn)行下面的命令向其發(fā)送不能處理的 SIGKILL
信號(hào):
$ kill -9 <PROCESS_ID>
這時(shí)程序應(yīng)該結(jié)束。
這些信號(hào)在 Node.js 程序中經(jīng)常用于處理正常的關(guān)閉事件。例如,當(dāng) Kubernetes Pod 終止時(shí),它將向程序發(fā)送 SIGTERM
信號(hào),之后啟動(dòng) 30 秒計(jì)時(shí)器。然后程序可以在這 30 秒內(nèi)正常關(guān)閉自己,關(guān)閉連接并保存數(shù)據(jù)。如果該進(jìn)程在此計(jì)時(shí)器后仍保持活動(dòng)狀態(tài),則 Kubernetes 將向其發(fā)送一個(gè) SIGKILL
。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“如何主動(dòng)終止Node.js進(jìn)程”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
網(wǎng)站欄目:如何主動(dòng)終止Node.js進(jìn)程
鏈接分享:http://muchs.cn/article24/iegpje.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)站導(dǎo)航、網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站設(shè)計(jì)公司、網(wǎng)站策劃、App設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
網(wǎng)頁(yè)設(shè)計(jì)公司知識(shí)