摘要:在行中,我們將子進程的連接到當前進程的。等待子進程通過退出函數如下所示。子進程的實現以下代碼用異步寫入以命令運行的子進程的我們為命令生成一個名為的獨立進程。而是子進程完成。沒有這個,將會在調用之前被輸出。
翻譯:瘋狂的技術宅
原文:http://2ality.com/2018/05/chi...
本文首發微信公眾號:jingchengyideng
歡迎關注,每天都給你推送新鮮的前端技術文章
在本中,我們在 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 連接到當前進程的 stdin。
B 行等待該過程完成。
等待子進程通過 Promise 退出函數 onExit()如下所示。
function onExit(childProcess: ChildProcess): Promise子進程的實現{ 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); }
我們為 shell 命令生成一個名為 sink 的獨立進程。用 writeToWritable 寫入 sink.stdin。它借助 await 異步執行并暫停,以避免緩沖區被消耗太多。
解釋:
在A行中,我們告訴 spawn() 通過 sink.stdin("pipe")訪問 stdin。 stdout 和 stderr 被轉發到 process.stdin 和 process.stderr,如前面所述。
在B行中不會 await 寫完成。而是 await 子進程 sink 完成。
接下來了解 streamWrite() 的工作原理。
寫流操作的 promiseNode.js 寫流的操作通常涉及回調(參見文檔)。代碼如下。
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()的工作方式是類似的。
從子進程中讀取數據下面的代碼使用異步迭代(C行)來讀取子進程的 stdout 中的內容:
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 轉發到process.stderr。
B行:開始 awat 直到 echoReadable() 完成。沒有這個 await,DONE 將會在調用 source.stdout 之前被輸出。
在子進程之間進行管道連接在下面的例子中,函數transform() 將會:
從 source 子進程的 stdout 中讀取內容。
將內容寫入 sink 子進程的 stdin。
換句話說,我們正在實現類似 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”中的“異步功能” 一章
歡迎繼續閱讀本專欄其它高贊文章:12個令人驚嘆的CSS實驗項目
世界頂級公司的前端面試都問些什么
CSS Flexbox 可視化手冊
過節很無聊?還是用 JavaScript 寫一個腦力小游戲吧!
從設計者的角度看 React
CSS粘性定位是怎樣工作的
一步步教你用HTML5 SVG實現動畫效果
程序員30歲前月薪達不到30K,該何去何從
第三方CSS安全嗎?
談談super(props) 的重要性
本文首發微信公眾號:jingchengyideng 歡迎掃描二維碼關注公眾號,每天都給你推送新鮮的前端技術文章文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102134.html
摘要:在中,只支持單線程。在這種場合下,如果能夠使用多進程,則可以為每個請求分配一個進程,從而可以更好地使用服務器端的資源。進程進程對象的屬性用于運行應用程序的可執行文件的絕對路徑的版本號及其各依賴的版本號當前運行的平臺用于讀入標準輸入流的對象。 Process 在Node.js中,只支持單線程。但是在應用程序中,如果只使用單線程進行操作,從接收請求開始到返回響應為止的這段時間內可能存在很長...
摘要:中各種用于讀取數據的對象對象描述用于讀取文件代表客戶端請求或服務器端響應代表一個端口對象用于創建子進程的標準輸出流。如果子進程和父進程共享輸入輸出流,則子進程的標準輸出流被廢棄用于創建子進程的標準錯誤輸出流。 9. stream流 fs模塊中集中文件讀寫方法的區別 用途 使用異步方式 使用同步方式 將文件完整讀入緩存區 readFile readFileSync 將文件部...
摘要:返回值對象利用給定的命令以及參數執行一個新的進程,如果沒有參數數組,那么將默認是一個空數組。當子進程執行完畢后將會執行的回調函數,參數有返回值對象在中運行一個命令,并緩存命令的輸出。 前言 眾所周知,Node.js在child_process模塊中提供了spawn和exec這兩個方法,用來開啟子進程執行指定程序。這兩個方法雖然目的一樣,但是既然Node.js為我們提供了兩個方法,那它...
摘要:在單核系統之上我們采用單進程單線程的模式來開發。由進程來管理所有的子進程,主進程不負責具體的任務處理,主要工作是負責調度和管理。模塊與模塊總結無論是模塊還是模塊,為了解決實例單線程運行,無法利用多核的問題而出現的。 前言 進程與線程是一個程序員的必知概念,面試經常被問及,但是一些文章內容只是講講理論知識,可能一些小伙伴并沒有真的理解,在實際開發中應用也比較少。本篇文章除了介紹概念,通過...
摘要:是一個全局變量,對象的屬性。的源碼啟動進程,評估時返回函數失敗。調用監聽器回調函數時會將的值作為唯一參數傳入。信號列表詳見標準的信號名,如等。返回一個對象,描述了進程所用的內存狀況,單位為字節。一旦當前事件循環結束,調用回調函數。 process是一個全局變量,global對象的屬性。它的作用是描述當前Node.js進程狀態的對象,提供了一個與操作系統的簡單接口。通常在你寫本地命令程序...
閱讀 748·2021-10-14 09:43
閱讀 2072·2021-09-30 09:48
閱讀 3440·2021-09-08 09:45
閱讀 1090·2021-09-02 15:41
閱讀 1878·2021-08-26 14:15
閱讀 770·2021-08-03 14:04
閱讀 2972·2019-08-30 15:56
閱讀 3072·2019-08-30 15:52