成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

一文聊聊Node.js中的進程與子進程

本篇文章帶大家深入了解下Node中的進程與子進程,希望對大家有所幫助!

一文聊聊Node.js中的進程與子進程

node.js極速入門課程:進入學習

進程:process模塊

process 模塊是 nodejs 提供給開發者用來和當前進程交互的工具,它的提供了很多實用的 API。【相關教程推薦:nodejs視頻教程】

從文檔出發,管中窺豹,進一步認識和學習 process 模塊:

  • 如何處理命令參數?
  • 如何處理工作目錄?
  • 如何處理異常?
  • 如何處理進程退出?
  • process 的標準流對象
  • 深入理解 process.nextTick

如何處理命令參數?

命令行參數指的是 2 個方面:

  • 傳給 node 的參數。例如 node --harmony script.js --version 中,--harmony 就是傳給 node 的參數
  • 傳給進程的參數。例如 node script.js --version --help 中,--version --help 就是傳給進程的參數

它們分別通過 process.argvprocess.execArgv 來獲得。

如何處理工作目錄?

通過process.cwd()可以獲取當前的工作目錄。

通過process.chdir(directory)可以切換當前的工作目錄,失敗后會拋出異常。實踐如下:

function safeChdir(dir) {     try {         process.chdir(dir);         return true;     } catch (error) {         return false;     } }
登錄后復制

如何處理異常?

uncaughtException 事件

Nodejs 可以通過 try-catch 來捕獲異常。如果異常未捕獲,則會一直從底向事件循環冒泡。如是冒泡到事件循環的異常沒被處理,那么就會導致當前進程異常退出。

根據文檔,可以通過監聽 process 的 uncaughtException 事件,來處理未捕獲的異常:

process.on("uncaughtException", (err, origin) => {     console.log(err.message); });  const a = 1 / b; console.log("abc"); // 不會執行
登錄后復制

上面的代碼,控制臺的輸出是:b is not defined。捕獲了錯誤信息,并且進程以0退出。開發者可以在 uncaughtException 事件中,清除一些已經分配的資源(文件描述符、句柄等),不推薦在其中重啟進程。

unhandledRejection 事件

如果一個 Promise 回調的異常沒有被.catch()捕獲,那么就會觸發 process 的 unhandledRejection 事件:

process.on("unhandledRejection", (err, promise) => {     console.log(err.message); });  Promise.reject(new Error("錯誤信息")); // 未被catch捕獲的異常,交由unhandledRejection事件處理
登錄后復制

warning 事件

告警不是 Node.js 和 Javascript 錯誤處理流程的正式組成部分。 一旦探測到可能導致應用性能問題,缺陷或安全隱患相關的代碼實踐,Node.js 就可發出告警。

比如前一段代碼中,如果出現未被捕獲的 promise 回調的異常,那么就會觸發 warning 事件。參考nodejs進階視頻講解:進入學習

如何處理進程退出?

process.exit() vs process.exitCode

一個 nodejs 進程,可以通過 process.exit() 來指定退出代碼,直接退出。不推薦直接使用 process.exit(),這會導致事件循環中的任務直接不被處理,以及可能導致數據的截斷和丟失(例如 stdout 的寫入)。

setTimeout(() => {     console.log("我不會執行"); });  process.exit(0);
登錄后復制

正確安全的處理是,設置 process.exitCode,并允許進程自然退出。

setTimeout(() => {     console.log("我不會執行"); });  process.exitCode = 1;
登錄后復制

beforeExit 事件

用于處理進程退出的事件有:beforeExit 事件 和 exit 事件。

當 Node.js 清空其事件循環并且沒有其他工作要安排時,會觸發 beforeExit 事件。例如在退出前需要一些異步操作,那么可以寫在 beforeExit 事件中:

let hasSend = false; process.on("beforeExit", () => {     if (hasSend) return; // 避免死循環      setTimeout(() => {         console.log("mock send data to serve");         hasSend = true;     }, 500); });  console.log("......."); // 輸出: // ....... // mock send data to serve
登錄后復制

注意:在 beforeExit 事件中如果是異步任務,那么又會被添加到任務隊列。此時,任務隊列完成所有任務后,又回觸發 beforeExit 事件。因此,不處理的話,可能出現死循環的情況。如果是顯式調用 exit(),那么不會觸發此事件。

exit 事件

在 exit 事件中,只能執行同步操作。在調用 'exit' 事件監聽器之后,Node.js 進程將立即退出,從而導致在事件循環中仍排隊的任何其他工作被放棄。

process 的標準流對象

process 提供了 3 個標準流。需要注意的是,它們有些在某些時候是同步阻塞的(請見文檔)。

  • process.stderr:WriteStream 類型,console.error的底層實現,默認對應屏幕
  • process.stdout:WriteStream 類型,console.log的底層實現,默認對應屏幕
  • process.stdin:ReadStream 類型,默認對應鍵盤輸入

下面是基于“生產者-消費者模型”的讀取控制臺輸入并且及時輸出的代碼:

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("結束"); });
登錄后復制

關于事件的含義,還是請看stream 的文檔。

深入理解 process.nextTick

我第一次看到 process.nextTick 的時候是比較懵的,看文檔可以知道,它的用途是:把回調函數作為微任務,放入事件循環的任務隊列中。但這么做的意義是什么呢?

因為 nodejs 并不適合計算密集型的應用,一個進程就一個線程,在當下時間點上,就一個事件在執行。那么,如果我們的事件占用了很多 cpu 時間,那么之后的事件就要等待非常久。所以,nodejs 的一個編程原則是盡量縮短每一個事件的執行事件。process.nextTick 的作用就在這,將一個大的任務分解成多個小的任務。示例代碼如下:

// 被拆分成2個函數執行 function BigThing() {     doPartThing();      process.nextTick(() => finishThing()); }
登錄后復制

在事件循環中,何時執行 nextTick 注冊的任務呢?請看下面的代碼:

setTimeout(function() {     console.log("第一個1秒");     process.nextTick(function() {         console.log("第一個1秒:nextTick");     }); }, 1000);  setTimeout(function() {     console.log("第2個1秒"); }, 1000);  console.log("我要輸出1");  process.nextTick(function() {     console.log("nextTick"); });  console.log("我要輸出2");
登錄后復制

輸出的結果如下,nextTick 是早于 setTimeout:

我要輸出1 我要輸出2 nextTick 第一個1秒 第一個1秒:nextTick 第2個1秒
登錄后復制

在瀏覽器端,nextTick 會退化成 setTimeout(callback, 0)。但在 nodejs 中請使用 nextTick 而不是 setTimeout,前者效率更高,并且嚴格來說,兩者創建的事件在任務隊列中順序并不一樣(請看前面的代碼)。

子進程:child_process模塊

掌握 nodejs 的 child_process 模塊能夠極大提高 nodejs 的開發能力,例如主從進程來優化 CPU 計算的問題,多進程開發等等。本文從以下幾個方面介紹 child_process 模塊的使用:

  • 創建子進程
  • 父子進程通信
  • 獨立子進程
  • 進程管道

創建子進程

nodejs 的 child_process 模塊創建子進程的方法:spawn, fork, exec, execFile。它們的關系如下:

  • fork, exec, execFile 都是通過 spawn 來實現的。
  • exec 默認會創建 shell。execFile 默認不會創建 shell,意味著不能使用 I/O 重定向、file glob,但效率更高。
  • spawn、exec、execFile 都有同步版本,可能會造成進程阻塞。

child_process.spawn()的使用:

const { spawn } = require("child_process"); // 返回ChildProcess對象,默認情況下其上的stdio不為null const ls = spawn("ls", ["-lh"]);  ls.stdout.on("data", data => {     console.log(`stdout: ${data}`); });  ls.stderr.on("data", data => {     console.error(`stderr: ${data}`); });  ls.on("close", code => {     console.log(`子進程退出,退出碼 ${code}`); });
登錄后復制

child_process.exec()的使用:

const { exec } = require("child_process"); // 通過回調函數來操作stdio exec("ls -lh", (err, stdout, stderr) => {     if (err) {         console.error(`執行的錯誤: ${err}`);         return;     }     console.log(`stdout: ${stdout}`);     console.error(`stderr: ${stderr}`); });
登錄后復制

父子進程通信

fork()返回的 ChildProcess 對象,監聽其上的 message 事件,來接受子進程消息;調用 send 方法,來實現 IPC。

parent.js 代碼如下:

const { fork } = require("child_process"); const cp = fork("./sub.js"); cp.on("message", msg => {     console.log("父進程收到消息:", msg); }); cp.send("我是父進程");
登錄后復制

sub.js 代碼如下:

process.on("message", m => {     console.log("子進程收到消息:", m); });  process.send("我是子進程");
登錄后復制

運行后結果:

父進程收到消息: 我是子進程 子進程收到消息: 我是父進程
登錄后復制

獨立子進程

在正常情況下,父進程一定會等待子進程退出后,才退出。如果想讓父進程先退出,不受到子進程的影響,那么應該:

  • 調用 ChildProcess 對象上的unref()
  • options.detached 設置為 true
  • 子進程的 stdio 不能是連接到父進程

main.js 代碼如下:

const { spawn } = require("child_process"); const subprocess = spawn(process.argv0, ["sub.js"], {     detached: true,     stdio: "ignore" });  subprocess.unref();
登錄后復制

sub.js 代碼如下:

setInterval(() => {}, 1000);
登錄后復制

進程管道

options.stdio 選項用于配置在父進程和子進程之間建立的管道。 默認情況下,子進程的 stdin、 stdout 和 stderr 會被重定向到 ChildProcess 對象上相應的 subprocess.stdin、subprocess.stdout 和 subprocess.stderr 流。 這意味著可以通過監聽其上的 data事件,在父進程中獲取子進程的 I/O 。

可以用來實現“重定向”:

const fs = require("fs"); const child_process = require("child_process");  const subprocess = child_process.spawn("ls", {     stdio: [         0, // 使用父進程的 stdin 用于子進程。         "pipe", // 把子進程的 stdout 通過管道傳到父進程 。         fs.openSync("err.out", "w") // 把子進程的 stderr 定向到一個文件。     ] });
登錄后復制

也可以用來實現"管道運算符":

const { spawn } = require("child_process");  const ps = spawn("ps", ["ax"]); const grep = spawn("grep", ["ssh"]);  ps.stdout.on("data", data => {     grep.stdin.write(data); });  ps.stderr.on("data", err => {     console.error(`ps stderr: ${err}`); });  ps.on("close", code => {     if (code !== 0) {         console.log(`ps 進程退出,退出碼 ${code}`);     }     grep.stdin.end(); });  grep.stdout.on("data", data => {     console.log(data.toString()); });  grep.stderr.on("data", data => {     console.error(`grep stderr: ${data}`); });  grep.on("close", code => {     if (code !== 0) {         console.log(`grep 進程退出,退出碼 ${code}`);     } });
登錄后復制

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品香蕉绿巨人登场| JIZZJIZZ无码中国在线观| 太深太粗太大太猛太爽了视频| 俄罗斯女人与马Z00Z视频| 一本色道无码道DVD在线观看| 无码中文字幕加勒比高清| 人马畜禽CORPORATION| 里番本子库绅士ACG全彩无码| 国内精品久久久久久久久电影网| 懂色av一区二区三区蜜臀| 国产A级毛多妇女视频| 成人国内精品久久久久影院| JIZZYOU中国少妇高潮| 成人国产一区二区精品小说| 国产产无码乱码精品久久鸭| 成人美女黄网站18禁免费| 国产成人无码一区二区在线播放| 成熟交BGMBGMBGM中国| 锕锕锕锕锕~好深啊APP网站| 91夜黄性一交一乱一色一情人| 永久免费AV网站可以直接看的| 亚洲乱码中文论理电影| 亚洲AV一本岛在线播放| 小SAO货CAO得你舒服么| 少妇人妻无码专区视频免费| 日韩高清在线中文字带字幕| 国产老妇伦国产熟女老妇久| 亚洲AV无码专区国产乱码4SE| 亚洲色无码中文字幕手机在线 | 娇妻借朋友高H繁交H| 国产女人好紧好爽| 国产成人一区二区精品视频| 精品国品一二三产品区别在线观看| 狠狠婷婷色五月中文字幕 | 久久人妻AV一区二区软件| 久久成人亚洲香蕉草草| 久久九九久精品国产88| 免费A级毛片在线播放不收费| 亚洲AV无码专区在线观看下载 | 玩稚嫩的小屁股眼AV| 国产SM鞭打折磨调教视频| 国产无线乱码一区二三区| 国产精品成人免费视频网站| 国产伦理一区二区| 国产高清一区二区三区视频| 野花韩国在线观看免费版5| 老熟女重囗味HDXX70星空| 精品一区二区三区不卡少妇av| 国产SUV精品一区二区| 国产欧美日韩精品丝袜高跟鞋| JK女自慰下面爆浆喷水| 中文字幕乱近親相姦| 久久国产中文娱乐网| 特级西西WWW444人体聚色| 人妻精品无码一区二区三区| 亚洲乱码日产精品B| 污污污WWW精品国产网站| 日日噜噜夜夜狠狠视频| 国产成人丝袜视频在线观看| 91麻豆精品无码一区二区三区| 亚洲图片小说激情综合| 国产综合精品一区二区三区| 成年女人A级毛片免费观看| 久久久久精品无码观看不卡| 一出一进一爽一粗一大视频免费的| 妺妺窝人体色聚色窝www视频| 伊人久久大香线蕉精品| 日本免费一区二区三区最新VR| 丁香花在线视频完整版| A4YY午夜福利视频无码| 18禁免费无码无遮挡不卡网站 | 被老头玩弄邻居人妻中文字幕| 中文无码制服丝袜人妻AV| 亚洲色欲AV无码成人专区| 亚洲AV成人精品五区| 无码高清一区二区三区 | 抖抈探探APP入口免费| 精品高朝久久久久9999| 日本XXXX色视频在线播放| 人人爽人人澡人人人人妻| 亚洲AV无码国产一区二区三区不| 妺妺窝人体色777777换脸| 欧美成人免费一区| 免费看美女被靠到爽的视频 | 欧美精产国品一二三产品区别 | 国产精品久久久久9999不卡| 亚洲欧美日本韩国| 欧美激情国产精品视频一区二区| 亚洲AV秘 无码一区二区三l| 久久精品国产只有精品66| 妺妺窝人体色WWW美女| 天天拍天天看天天做| 人妻熟妇久久久久久XXX| 亚洲AV无码成电影在线播放| 99久久久国产精品免费牛牛| 国产精品免费无遮挡无码永久视频 | 怡红院AV一区二区三区| 国产SM残忍打屁股调教视频| 老头扒开粉嫩的小缝亲吻网站| 少妇寂寞偷公乱400章深夜书屋| 少妇侧入内射一区二区| 一本色道久久88加勒比—综合 | 人人澡人人妻人人爽少妇| 亚洲精品无码精品MV在线观看| 欧美精品偷自拍另类在线观看| 国产乱子伦高清露脸对白| 久久人人97超碰CAOPORE| 欧美成人A猛片在线观看| 亚洲国产成人久久综合| 欧美精品少妇XXXXX喷水| 亚洲阿V天堂无码2020| 色天使综合婷婷国产日韩AV| 久久99国产精品久久99小说| 欧美无人区码卡二卡3卡2022| 丰满人妻被公侵犯完整版| 99热精品国产三级在线| 国产精品久久久久精品三级| 男人吵架后疯狂要你什么心理| 他把胸罩撕了捏胸吃奶| 亚洲午夜性春猛交XXXX偷窥| 国产精品久久久久成人| 欧美少妇XXXXX| 中国老太太BBVBBⅤ| WC女厕撒尿七Ⅴ偷拍| 免费120秒体验试看5次| 欧美性猛交XXXX乱大交视频| 无码av无码免费一区二区毛片| 八区精品色欲人妻综合网| 国产麻花豆剧传媒精品免费| 少妇性饥渴无码A区免费| 边做边爱MP3在线播放免费观看| 绯色精品人妻av一区二区| 男人女人做爽爽18禁免费| 日韩AV无码成人精品国产| Japanese日本护士XXXX18一19| 国产V亚洲V欧美V专区| 少妇高潮喷水惨叫久久久久电影| 自拍偷在线精品自拍偷99| 国产欧美精品一区AⅤ影院| 四虎影库884AA.WWW| 成人女人A级毛片免费软件| 久久久国产精品人妻AⅤ麻豆| 亚洲午夜无码毛片Av| 可播放的免费男同GAY| 好男人好视频资源在线播放| 麻花豆传媒MV在线播放| 日本亲近相奷中文字幕 | 国产无遮挡又黄又爽又色| 色噜噜狠狠一区二区三区果冻| 成人一区二区免费中文字幕视频| 免费中国大但人文艺术在线观看| 9L国产精品久久久久麻豆| 免费无遮挡无码永久在线观看视频 | 小诗的公交车日记第9章| 成人国内精品视频在线观看| 色综合天天综合狠狠爱_| 粗大挺进尤物人妻| 无码欧亚熟妇人妻AV在线| 成人无码影片精品久久久| 无码人妻一区二区三区免费N鬼沢| 国语对白做受XXXXX在线| 清纯JK校花被啪啪AV免费| 国产AV夜夜欢一区二区三区| 天天狠天天透天天爱综合| 好紧我太爽了视频免费| .一区二区三区在线 | 欧洲| 狠狠躁夜夜躁人人爽天天| 人妻18毛片A级毛片免费看| 国产VA免费精品高清在线| 我趁老师睡觉偷偷的脱她内裤| 国产94在线 | 亚洲| 欧美日韩在线亚洲一区蜜芽| 国产精品久久久久久久久鸭| 一本久道视频无线视频| 日本黄页网站免费观看| 国产亚洲精品自在久久| 亚洲AV成人永久无在线观看| 妺妺窝人体色www聚色窝图| 国产激情久久久久影院小草| 在线亚洲人成电影网站色WWW| 色偷偷AV男人的天堂京东热| 国产CHINESE男男GAYGAY网站| 一区二区三区av在线| 玩弄粉嫩少妇高潮出白浆AⅤ| 泷泽萝拉AV种子| S货叫大点声C烂你的SB视频| 亚洲AV综合AV一区| 肉妇春潮干柴烈火MYFDUCC| 黑人巨鞭大战丰满少妇| 野花社区WWW官网在线观看| 水多的女人男人最上瘾| 国产成人精品亚洲午夜麻豆| 亚洲精品国产AV天美传媒| 久久亚洲AV成人无码国产最大 | 高潮和狂野射精合集| 人妻少妇AV中文字幕乱码| 久久久久亚洲AV成人网址| CAOPOREN超碰| 日韩成人无码专区一视频| 久久久免费无码成人影片|