摘要:在行中,我們將子進程的連接到當(dāng)前進程的。等待子進程通過退出函數(shù)如下所示。子進程的實現(xiàn)以下代碼用異步寫入以命令運行的子進程的我們?yōu)槊钌梢粋€名為的獨立進程。而是子進程完成。沒有這個,將會在調(diào)用之前被輸出。
翻譯:瘋狂的技術(shù)宅
原文:http://2ality.com/2018/05/chi...
本文首發(fā)微信公眾號:jingchengyideng
歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章
在本中,我們在 Node.js 中把 shell 命令作為子進程運行。然后異步讀取這些進程的 stdout 并寫入其 stdin。
在子進程中運行 shell 命令首先從在子進程中運行 shell 命令開始:
const {onExit} = require("@rauschma/stringio"); const {spawn} = require("child_process"); async function main() { const filePath = process.argv[2]; console.log("INPUT: "+filePath); const childProcess = spawn("cat", [filePath], {stdio: [process.stdin, process.stdout, process.stderr]}); // (A) await onExit(childProcess); // (B) console.log("### DONE"); } main();
解釋:
我們用了 spawn(),它可以使我們在命令運行時訪問命令的 stdin,stdout 和 stderr。
在 A 行中,我們將子進程的 stdin 連接到當(dāng)前進程的 stdin。
B 行等待該過程完成。
等待子進程通過 Promise 退出函數(shù) onExit()如下所示。
function onExit(childProcess: ChildProcess): Promise子進程的實現(xiàn){ return new Promise((resolve, reject) => { childProcess.once("exit", (code: number, signal: string) => { if (code === 0) { resolve(undefined); } else { reject(new Error("Exit with error code: "+code)); } }); childProcess.once("error", (err: Error) => { reject(err); }); }); }
以下代碼用 @rauschma/stringio 異步寫入以 shell 命令運行的子進程的 stdin:
const {streamWrite, streamEnd, onExit} = require("@rauschma/stringio"); const {spawn} = require("child_process"); async function main() { const sink = spawn("cat", [], {stdio: ["pipe", process.stdout, process.stderr]}); // (A) writeToWritable(sink.stdin); // (B) await onExit(sink); console.log("### DONE"); } main(); async function writeToWritable(writable) { await streamWrite(writable, "First line "); await streamWrite(writable, "Second line "); await streamEnd(writable); }
我們?yōu)?shell 命令生成一個名為 sink 的獨立進程。用 writeToWritable 寫入 sink.stdin。它借助 await 異步執(zhí)行并暫停,以避免緩沖區(qū)被消耗太多。
解釋:
在A行中,我們告訴 spawn() 通過 sink.stdin("pipe")訪問 stdin。 stdout 和 stderr 被轉(zhuǎn)發(fā)到 process.stdin 和 process.stderr,如前面所述。
在B行中不會 await 寫完成。而是 await 子進程 sink 完成。
接下來了解 streamWrite() 的工作原理。
寫流操作的 promiseNode.js 寫流的操作通常涉及回調(diào)(參見文檔)。代碼如下。
function streamWrite( stream: Writable, chunk: string|Buffer|Uint8Array, encoding="utf8"): Promise{ return new Promise((resolve, reject) => { const errListener = (err: Error) => { stream.removeListener("error", errListener); reject(err); }; stream.addListener("error", errListener); const callback = () => { stream.removeListener("error", errListener); resolve(undefined); }; stream.write(chunk, encoding, callback); }); }
streamEnd()的工作方式是類似的。
從子進程中讀取數(shù)據(jù)下面的代碼使用異步迭代(C行)來讀取子進程的 stdout 中的內(nèi)容:
const {chunksToLinesAsync, chomp} = require("@rauschma/stringio"); const {spawn} = require("child_process"); async function main() { const filePath = process.argv[2]; console.log("INPUT: "+filePath); const source = spawn("cat", [filePath], {stdio: ["ignore", "pipe", process.stderr]}); // (A) await echoReadable(source.stdout); // (B) console.log("### DONE"); } main(); async function echoReadable(readable) { for await (const line of chunksToLinesAsync(readable)) { // (C) console.log("LINE: "+chomp(line)) } }
解釋:
A行:我們忽略 stdin,希望通過流訪問 stdout 并將 stderr 轉(zhuǎn)發(fā)到process.stderr。
B行:開始 awat 直到 echoReadable() 完成。沒有這個 await,DONE 將會在調(diào)用 source.stdout 之前被輸出。
在子進程之間進行管道連接在下面的例子中,函數(shù)transform() 將會:
從 source 子進程的 stdout 中讀取內(nèi)容。
將內(nèi)容寫入 sink 子進程的 stdin。
換句話說,我們正在實現(xiàn)類似 Unix 管道的功能:
cat someFile.txt | transform() | cat
這是代碼:
const {chunksToLinesAsync, streamWrite, streamEnd, onExit} = require("@rauschma/stringio"); const {spawn} = require("child_process"); async function main() { const filePath = process.argv[2]; console.log("INPUT: "+filePath); const source = spawn("cat", [filePath], {stdio: ["ignore", "pipe", process.stderr]}); const sink = spawn("cat", [], {stdio: ["pipe", process.stdout, process.stderr]}); transform(source.stdout, sink.stdin); await onExit(sink); console.log("### DONE"); } main(); async function transform(readable, writable) { for await (const line of chunksToLinesAsync(readable)) { await streamWrite(writable, "@ "+line); } await streamEnd(writable); }擴展閱讀
博客:“通過 Node.js 的異步迭代讀取流”
“探索ES2018和ES2019”中的“異步迭代 一章
“探索ES2016和ES2017”中的“異步功能” 一章
歡迎繼續(xù)閱讀本專欄其它高贊文章:12個令人驚嘆的CSS實驗項目
世界頂級公司的前端面試都問些什么
CSS Flexbox 可視化手冊
過節(jié)很無聊?還是用 JavaScript 寫一個腦力小游戲吧!
從設(shè)計者的角度看 React
CSS粘性定位是怎樣工作的
一步步教你用HTML5 SVG實現(xiàn)動畫效果
程序員30歲前月薪達不到30K,該何去何從
第三方CSS安全嗎?
談?wù)剆uper(props) 的重要性
本文首發(fā)微信公眾號:jingchengyideng 歡迎掃描二維碼關(guān)注公眾號,每天都給你推送新鮮的前端技術(shù)文章文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/102134.html
摘要:在中,只支持單線程。在這種場合下,如果能夠使用多進程,則可以為每個請求分配一個進程,從而可以更好地使用服務(wù)器端的資源。進程進程對象的屬性用于運行應(yīng)用程序的可執(zhí)行文件的絕對路徑的版本號及其各依賴的版本號當(dāng)前運行的平臺用于讀入標(biāo)準(zhǔn)輸入流的對象。 Process 在Node.js中,只支持單線程。但是在應(yīng)用程序中,如果只使用單線程進行操作,從接收請求開始到返回響應(yīng)為止的這段時間內(nèi)可能存在很長...
摘要:中各種用于讀取數(shù)據(jù)的對象對象描述用于讀取文件代表客戶端請求或服務(wù)器端響應(yīng)代表一個端口對象用于創(chuàng)建子進程的標(biāo)準(zhǔn)輸出流。如果子進程和父進程共享輸入輸出流,則子進程的標(biāo)準(zhǔn)輸出流被廢棄用于創(chuàng)建子進程的標(biāo)準(zhǔn)錯誤輸出流。 9. stream流 fs模塊中集中文件讀寫方法的區(qū)別 用途 使用異步方式 使用同步方式 將文件完整讀入緩存區(qū) readFile readFileSync 將文件部...
摘要:返回值對象利用給定的命令以及參數(shù)執(zhí)行一個新的進程,如果沒有參數(shù)數(shù)組,那么將默認是一個空數(shù)組。當(dāng)子進程執(zhí)行完畢后將會執(zhí)行的回調(diào)函數(shù),參數(shù)有返回值對象在中運行一個命令,并緩存命令的輸出。 前言 眾所周知,Node.js在child_process模塊中提供了spawn和exec這兩個方法,用來開啟子進程執(zhí)行指定程序。這兩個方法雖然目的一樣,但是既然Node.js為我們提供了兩個方法,那它...
摘要:在單核系統(tǒng)之上我們采用單進程單線程的模式來開發(fā)。由進程來管理所有的子進程,主進程不負責(zé)具體的任務(wù)處理,主要工作是負責(zé)調(diào)度和管理。模塊與模塊總結(jié)無論是模塊還是模塊,為了解決實例單線程運行,無法利用多核的問題而出現(xiàn)的。 前言 進程與線程是一個程序員的必知概念,面試經(jīng)常被問及,但是一些文章內(nèi)容只是講講理論知識,可能一些小伙伴并沒有真的理解,在實際開發(fā)中應(yīng)用也比較少。本篇文章除了介紹概念,通過...
摘要:是一個全局變量,對象的屬性。的源碼啟動進程,評估時返回函數(shù)失敗。調(diào)用監(jiān)聽器回調(diào)函數(shù)時會將的值作為唯一參數(shù)傳入。信號列表詳見標(biāo)準(zhǔn)的信號名,如等。返回一個對象,描述了進程所用的內(nèi)存狀況,單位為字節(jié)。一旦當(dāng)前事件循環(huán)結(jié)束,調(diào)用回調(diào)函數(shù)。 process是一個全局變量,global對象的屬性。它的作用是描述當(dāng)前Node.js進程狀態(tài)的對象,提供了一個與操作系統(tǒng)的簡單接口。通常在你寫本地命令程序...
閱讀 862·2021-10-14 09:43
閱讀 2192·2021-09-30 09:48
閱讀 3534·2021-09-08 09:45
閱讀 1171·2021-09-02 15:41
閱讀 1957·2021-08-26 14:15
閱讀 853·2021-08-03 14:04
閱讀 3044·2019-08-30 15:56
閱讀 3133·2019-08-30 15:52