摘要:事件的觸發(fā)頻次同樣是由實(shí)現(xiàn)者決定,譬如在進(jìn)行文件讀取時(shí),可能每行都會觸發(fā)一次而在請求處理時(shí),可能數(shù)的數(shù)據(jù)才會觸發(fā)一次。如果有參數(shù)傳入,它會讓可讀流停止流向某個特定的目的地,否則,它會移除所有目的地。
本文節(jié)選自 Node.js CheatSheet | Node.js 語法基礎(chǔ)、框架使用與實(shí)踐技巧,也可以閱讀 JavaScript CheatSheet 或者 現(xiàn)代 Web 開發(fā)基礎(chǔ)與工程實(shí)踐 了解更多 JavaScript/Node.js 的實(shí)際應(yīng)用。
Stream 是 Node.js 中的基礎(chǔ)概念,類似于 EventEmitter,專注于 IO 管道中事件驅(qū)動的數(shù)據(jù)處理方式;類比于數(shù)組或者映射,Stream 也是數(shù)據(jù)的集合,只不過其代表了不一定正在內(nèi)存中的數(shù)據(jù)。。Node.js 的 Stream 分為以下類型:
Readable Stream: 可讀流,數(shù)據(jù)的產(chǎn)生者,譬如 process.stdin
Writable Stream: 可寫流,數(shù)據(jù)的消費(fèi)者,譬如 process.stdout 或者 process.stderr
Duplex Stream: 雙向流,即可讀也可寫
Transform Stream: 轉(zhuǎn)化流,數(shù)據(jù)的轉(zhuǎn)化者
Stream 本身提供了一套接口規(guī)范,很多 Node.js 中的內(nèi)建模塊都遵循了該規(guī)范,譬如著名的 fs 模塊,即是使用 Stream 接口來進(jìn)行文件讀寫;同樣的,每個 HTTP 請求是可讀流,而 HTTP 響應(yīng)則是可寫流。
Readable Streamconst stream = require("stream"); const fs = require("fs"); const readableStream = fs.createReadStream(process.argv[2], { encoding: "utf8" }); // 手動設(shè)置流數(shù)據(jù)編碼 // readableStream.setEncoding("utf8"); let wordCount = 0; readableStream.on("data", function(data) { wordCount += data.split(/s{1,}/).length; }); readableStream.on("end", function() { // Don"t count the end of the file. console.log("%d %s", --wordCount, process.argv[2]); });
當(dāng)我們創(chuàng)建某個可讀流時(shí),其還并未開始進(jìn)行數(shù)據(jù)流動;添加了 data 的事件監(jiān)聽器,它才會變成流動態(tài)的。在這之后,它就會讀取一小塊數(shù)據(jù),然后傳到我們的回調(diào)函數(shù)里面。 data 事件的觸發(fā)頻次同樣是由實(shí)現(xiàn)者決定,譬如在進(jìn)行文件讀取時(shí),可能每行都會觸發(fā)一次;而在 HTTP 請求處理時(shí),可能數(shù) KB 的數(shù)據(jù)才會觸發(fā)一次??梢詤⒖?nodejs/readable-stream/_stream_readable 中的相關(guān)實(shí)現(xiàn),發(fā)現(xiàn) on 函數(shù)會觸發(fā) resume 方法,該方法又會調(diào)用 flow 函數(shù)進(jìn)行流讀?。?/p>
// function on if (ev === "data") { // Start flowing on next tick if stream isn"t explicitly paused if (this._readableState.flowing !== false) this.resume(); } ... // function flow while (state.flowing && stream.read() !== null) {}
我們還可以監(jiān)聽 readable 事件,然后手動地進(jìn)行數(shù)據(jù)讀?。?/p>
let data = ""; let chunk; readableStream.on("readable", function() { while ((chunk = readableStream.read()) != null) { data += chunk; } }); readableStream.on("end", function() { console.log(data); });
Readable Stream 還包括如下常用的方法:
Readable.pause(): 這個方法會暫停流的流動。換句話說就是它不會再觸發(fā) data 事件。
Readable.resume(): 這個方法和上面的相反,會讓暫停流恢復(fù)流動。
Readable.unpipe(): 這個方法會把目的地移除。如果有參數(shù)傳入,它會讓可讀流停止流向某個特定的目的地,否則,它會移除所有目的地。
在日常開發(fā)中,我們可以用 stream-wormhole 來模擬消耗可讀流:
sendToWormhole(readStream, true);Writable Stream
readableStream.on("data", function(chunk) { writableStream.write(chunk); }); writableStream.end();
當(dāng) end() 被調(diào)用時(shí),所有數(shù)據(jù)會被寫入,然后流會觸發(fā)一個 finish 事件。注意在調(diào)用 end() 之后,你就不能再往可寫流中寫入數(shù)據(jù)了。
const { Writable } = require("stream"); const outStream = new Writable({ write(chunk, encoding, callback) { console.log(chunk.toString()); callback(); } }); process.stdin.pipe(outStream);
Writable Stream 中同樣包含一些與 Readable Stream 相關(guān)的重要事件:
error: 在寫入或鏈接發(fā)生錯誤時(shí)觸發(fā)
pipe: 當(dāng)可讀流鏈接到可寫流時(shí),這個事件會觸發(fā)
unpipe: 在可讀流調(diào)用 unpipe 時(shí)會觸發(fā)
Pipe | 管道const fs = require("fs"); const inputFile = fs.createReadStream("REALLY_BIG_FILE.x"); const outputFile = fs.createWriteStream("REALLY_BIG_FILE_DEST.x"); // 當(dāng)建立管道時(shí),才發(fā)生了流的流動 inputFile.pipe(outputFile);
多個管道順序調(diào)用,即是構(gòu)建了鏈接(Chaining):
const fs = require("fs"); const zlib = require("zlib"); fs.createReadStream("input.txt.gz") .pipe(zlib.createGunzip()) .pipe(fs.createWriteStream("output.txt"));
管道也常用于 Web 服務(wù)器中的文件處理,以 Egg.js 中的應(yīng)用為例,我們可以從 Context 中獲取到文件流并將其傳入到可寫文件流中:
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/97600.html
摘要:流是基于事件的用于管理和處理數(shù)據(jù)而且有不錯的效率借助事件和非阻塞庫流模塊允許在其可用的時(shí)候動態(tài)處理在其不需要的時(shí)候釋放掉使用流的好處舉一個讀取文件的例子使用同步讀取一個文件程序會被阻塞所有的數(shù)據(jù)都會被讀取到內(nèi)存中換用讀取文件程序不會被阻塞但 流是基于事件的API,用于管理和處理數(shù)據(jù),而且有不錯的效率.借助事件和非阻塞I/O庫,流模塊允許在其可用的時(shí)候動態(tài)處理,在其不需要的時(shí)候釋放掉. ...
摘要:前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。對該漏洞的綜合評級為高危。目前,相關(guān)利用方式已經(jīng)在互聯(lián)網(wǎng)上公開,近期出現(xiàn)攻擊嘗試爆發(fā)的可能。 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開發(fā)教程、工程實(shí)踐、深度閱讀、開源項(xiàng)目、巔峰人生等欄目。歡...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡介現(xiàn)在,越來越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說明 2017-12-14 我發(fā)了一篇文章《沒用過Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車的還坐過站了。大家可以很...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡介現(xiàn)在,越來越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說明 2017-12-14 我發(fā)了一篇文章《沒用過Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車的還坐過站了。大家可以很...
閱讀 1698·2021-10-09 09:44
閱讀 3290·2021-10-08 10:04
閱讀 2542·2021-09-26 09:55
閱讀 3944·2021-09-22 10:02
閱讀 3358·2019-08-29 17:08
閱讀 1156·2019-08-29 15:08
閱讀 3023·2019-08-26 13:52
閱讀 3326·2019-08-26 13:34