詳解Node.JS模塊 process
process 模塊是 nodejs 提供給開發(fā)者用來和當(dāng)前進(jìn)程交互的工具,它的提供了很多實(shí)用的 API。從文檔出發(fā),管中窺豹,進(jìn)一步認(rèn)識(shí)和學(xué)習(xí) process 模塊:
- 如何處理命令參數(shù)?
- 如何處理工作目錄?
- 如何處理異常?
- 如何處理進(jìn)程退出?
- process 的標(biāo)準(zhǔn)流對象
- 深入理解 process.nextTick
如何處理命令參數(shù)?
命令行參數(shù)指的是 2 個(gè)方面:
- 傳給 node 的參數(shù)。例如
node --harmony script.js --version中,--harmony就是傳給 node 的參數(shù) - 傳給進(jìn)程的參數(shù)。例如
node script.js --version --help中,--version --help就是傳給進(jìn)程的參數(shù)
它們分別通過 process.argv 和 process.execArgv 來獲得。
如何處理工作目錄?
通過process.cwd()可以獲取當(dāng)前的工作目錄。
通過process.chdir(directory)可以切換當(dāng)前的工作目錄,失敗后會(huì)拋出異常。實(shí)踐如下:
function safeChdir(dir) {
try {
process.chdir(dir);
return true;
} catch (error) {
return false;
}
}
如何處理異常?
uncaughtException 事件
Nodejs 可以通過 try-catch 來捕獲異常。如果異常未捕獲,則會(huì)一直從底向事件循環(huán)冒泡。如是冒泡到事件循環(huán)的異常沒被處理,那么就會(huì)導(dǎo)致當(dāng)前進(jìn)程異常退出。
根據(jù)文檔,可以通過監(jiān)聽 process 的 uncaughtException 事件,來處理未捕獲的異常:
process.on("uncaughtException", (err, origin) => {
console.log(err.message);
});
const a = 1 / b;
console.log("abc"); // 不會(huì)執(zhí)行
上面的代碼,控制臺(tái)的輸出是:b is not defined。捕獲了錯(cuò)誤信息,并且進(jìn)程以0退出。開發(fā)者可以在 uncaughtException 事件中,清除一些已經(jīng)分配的資源(文件描述符、句柄等),不推薦在其中重啟進(jìn)程。
unhandledRejection 事件
如果一個(gè) Promise 回調(diào)的異常沒有被.catch()捕獲,那么就會(huì)觸發(fā) process 的 unhandledRejection 事件:
process.on("unhandledRejection", (err, promise) => {
console.log(err.message);
});
Promise.reject(new Error("錯(cuò)誤信息")); // 未被catch捕獲的異常,交由unhandledRejection事件處理
warning 事件
告警不是 Node.js 和 Javascript 錯(cuò)誤處理流程的正式組成部分。 一旦探測到可能導(dǎo)致應(yīng)用性能問題,缺陷或安全隱患相關(guān)的代碼實(shí)踐,Node.js 就可發(fā)出告警。
比如前一段代碼中,如果出現(xiàn)未被捕獲的 promise 回調(diào)的異常,那么就會(huì)觸發(fā) warning 事件。
如何處理進(jìn)程退出?
process.exit() vs process.exitCode
一個(gè) nodejs 進(jìn)程,可以通過 process.exit() 來指定退出代碼,直接退出。不推薦直接使用 process.exit(),這會(huì)導(dǎo)致事件循環(huán)中的任務(wù)直接不被處理,以及可能導(dǎo)致數(shù)據(jù)的截?cái)嗪蛠G失(例如 stdout 的寫入)。
setTimeout(() => {
console.log("我不會(huì)執(zhí)行");
});
process.exit(0);
正確安全的處理是,設(shè)置 process.exitCode,并允許進(jìn)程自然退出。
setTimeout(() => {
console.log("我不會(huì)執(zhí)行");
});
process.exitCode = 1;
beforeExit 事件
用于處理進(jìn)程退出的事件有:beforeExit 事件 和 exit 事件。
當(dāng) Node.js 清空其事件循環(huán)并且沒有其他工作要安排時(shí),會(huì)觸發(fā) beforeExit 事件。例如在退出前需要一些異步操作,那么可以寫在 beforeExit 事件中:
let hasSend = false;
process.on("beforeExit", () => {
if (hasSend) return; // 避免死循環(huán)
setTimeout(() => {
console.log("mock send data to serve");
hasSend = true;
}, 500);
});
console.log(".......");
// 輸出:
// .......
// mock send data to serve
注意:在 beforeExit 事件中如果是異步任務(wù),那么又會(huì)被添加到任務(wù)隊(duì)列。此時(shí),任務(wù)隊(duì)列完成所有任務(wù)后,又回觸發(fā) beforeExit 事件。因此,不處理的話,可能出現(xiàn)死循環(huán)的情況。如果是顯式調(diào)用 exit(),那么不會(huì)觸發(fā)此事件。
exit 事件
在 exit 事件中,只能執(zhí)行同步操作。在調(diào)用 ‘exit' 事件監(jiān)聽器之后,Node.js 進(jìn)程將立即退出,從而導(dǎo)致在事件循環(huán)中仍排隊(duì)的任何其他工作被放棄。
process 的標(biāo)準(zhǔn)流對象
process 提供了 3 個(gè)標(biāo)準(zhǔn)流。需要注意的是,它們有些在某些時(shí)候是同步阻塞的(請見文檔)。
- process.stderr:WriteStream 類型,console.error的底層實(shí)現(xiàn),默認(rèn)對應(yīng)屏幕
- process.stdout:WriteStream 類型,console.log的底層實(shí)現(xiàn),默認(rèn)對應(yīng)屏幕
- process.stdin:ReadStream 類型,默認(rèn)對應(yīng)鍵盤輸入
下面是基于“生產(chǎn)者-消費(fèi)者模型”的讀取控制臺(tái)輸入并且及時(shí)輸出的代碼:
process.stdin.setEncoding("utf8");
process.stdin.on("readable", () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
process.stdout.write(`>>> ${chunk}`);
}
});
process.stdin.on("end", () => {
process.stdout.write("結(jié)束");
});
關(guān)于事件的含義,還是請看stream 的文檔。
深入理解 process.nextTick
我第一次看到 process.nextTick 的時(shí)候是比較懵的,看文檔可以知道,它的用途是:把回調(diào)函數(shù)作為微任務(wù),放入事件循環(huán)的任務(wù)隊(duì)列中。但這么做的意義是什么呢?
因?yàn)?nodejs 并不適合計(jì)算密集型的應(yīng)用,一個(gè)進(jìn)程就一個(gè)線程,在當(dāng)下時(shí)間點(diǎn)上,就一個(gè)事件在執(zhí)行。那么,如果我們的事件占用了很多 cpu 時(shí)間,那么之后的事件就要等待非常久。所以,nodejs 的一個(gè)編程原則是盡量縮短每一個(gè)事件的執(zhí)行事件。process.nextTick 的作用就在這,將一個(gè)大的任務(wù)分解成多個(gè)小的任務(wù)。示例代碼如下:
// 被拆分成2個(gè)函數(shù)執(zhí)行
function BigThing() {
doPartThing();
process.nextTick(() => finishThing());
}
在事件循環(huán)中,何時(shí)執(zhí)行 nextTick 注冊的任務(wù)呢?請看下面的代碼:
setTimeout(function() {
console.log("第一個(gè)1秒");
process.nextTick(function() {
console.log("第一個(gè)1秒:nextTick");
});
}, 1000);
setTimeout(function() {
console.log("第2個(gè)1秒");
}, 1000);
console.log("我要輸出1");
process.nextTick(function() {
console.log("nextTick");
});
console.log("我要輸出2");
輸出的結(jié)果如下,nextTick 是早于 setTimeout:
我要輸出1
我要輸出2
nextTick
第一個(gè)1秒
第一個(gè)1秒:nextTick
第2個(gè)1秒
在瀏覽器端,nextTick 會(huì)退化成 setTimeout(callback, 0)。但在 nodejs 中請使用 nextTick 而不是 setTimeout,前者效率更高,并且嚴(yán)格來說,兩者創(chuàng)建的事件在任務(wù)隊(duì)列中順序并不一樣(請看前面的代碼)。
以上就是詳解Node.JS模塊 process的詳細(xì)內(nèi)容,更多關(guān)于Node.JS模塊 process的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Express + Node.js實(shí)現(xiàn)登錄攔截器的實(shí)例代碼
本篇文章主要介紹了Express + Node.js實(shí)現(xiàn)攔截器的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
Node.js 實(shí)現(xiàn)簡單的無侵入式緩存框架的方法
這篇文章主要介紹了Node.js 實(shí)現(xiàn)簡單的無侵入式緩存框架的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07
詳解如何在Node.js中實(shí)現(xiàn)HTTP/2推送信息
HTTP/2 是一種現(xiàn)代化的網(wǎng)絡(luò)協(xié)議,它引入了多路復(fù)用、頭部壓縮和服務(wù)器推送等特性,其中,服務(wù)器推送允許服務(wù)器在客戶端請求資源時(shí),主動(dòng)推送額外的資源,提升頁面加載速度,下面將介紹如何在 Node.js 中實(shí)現(xiàn) HTTP/2 推送信息,需要的朋友可以參考下2024-12-12
Windows上node.js的多版本管理工具用法實(shí)例分析
這篇文章主要介紹了Windows上node.js的多版本管理工具用法,結(jié)合實(shí)例形式分析了Windows平臺(tái)上node.js多版本管理工具nvm-windows的相關(guān)使用技巧,需要的朋友可以參考下2019-11-11
node.js中的querystring.stringify方法使用說明
這篇文章主要介紹了node.js中的querystring.stringify方法使用說明,本文介紹了querystring.stringify的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12

