NodeJS —— 自定義流的實現

 

概述

常見的自定義流有四種,Readable(可讀流)、Writable(可寫流)、Duplex(雙工流)和 Transform(轉換流),常見的自定義流應用有 HTTP 請求、響應,crypto 加密,進程 stdin 通訊等等。javascript


stream 模塊介紹

在 NodeJS 中要想實現自定義流,須要依賴模塊 stream,直接引入,不需下載,全部種類的流都是繼承這個模塊內部提供的對應不一樣種類的類來實現的。php

實現一個自定義可讀流 Readable

一、建立自定義可讀流的類 MyRead

實現自定義可讀流需建立一個類爲 MyRead,並繼承 stream 中的 Readable 類,重寫 _read 方法,這是全部自定義流的固定套路。java

let { Readable } = require("stream"); // 建立自定義可讀流的類 class MyRead extends Readable { constructor() { super(); this.index = 0; } // 重寫自定義的可讀流的 _read 方法 _read() { this.index++; this.push(this.index + ""); if (this.index === 3) { this.push(null); } } } 複製代碼

咱們本身寫的 _read 方法會先查找並執行,在讀取時使用 push 方法將數據讀取出來,直到 push 的值爲 null 纔會中止,不然會認爲沒有讀取完成,會繼續調用 _readnode

二、驗證自定義可讀流

let myRead = new MyRead(); myRead.on("data", data => { console.log(data); }); myRead.on("end", function() { console.log("讀取完成"); }); // <Buffer 31> // <Buffer 32> // <Buffer 33> // 讀取完成 複製代碼

實現一個自定義可寫流 Writable

一、建立自定義可寫流的類 MyWrite

建立一個類名爲 MyWrite,並繼承 stream 中的 Writable 類,重寫 _write 方法。web

let { Writable } = require("stream"); // 建立自定義可寫流的類 class MyWrite extends Writable { // 重寫自定義的可寫流的 _write 方法 _write(chunk, encoding, callback)) { callback(); // 將緩存區寫入文件 } } 複製代碼

寫入內容時默認第一次寫入直接寫入文件,後面的寫入都寫入緩存區,若是不調用 callback 只能默認第一次寫入文件,調用 callback 會將緩存區清空並寫入文件。緩存

二、驗證自定義可寫流

let myWrite = new MyWrite(); myWrite.write("hello", "utf8", () => { console.log("hello ok"); }); myWrite.write("world", "utf8", () => { console.log("world ok"); }); // hello ok // world ok 複製代碼

實現一個自定義雙工流 Duplex

一、建立自定義可雙工流的類 MyDuplex

雙工流的能夠理解爲便可讀又可寫的流,建立一個類名爲 MyDuplex,並繼承 stream 中的 Duplex 類,因爲雙工流便可讀又可寫,需重寫 _read_write 方法。服務器

let { Duplex } = require("stream"); // 建立自定義雙工流的類 class MyDuplex extends Duplex { // 重寫自定義的雙工流的 _read 方法 _read() { this.push("123"); this.push(null); } // 重寫自定義的雙工流的 _write 方法 _write(chunk, encoding, callback)) { callback(); } } 複製代碼

雙工流分別具有 ReadableWritable 的功能,可是讀和寫互不影響,互不關聯。post

二、驗證自定義雙工流

let myDuplex = new MyDuplex(); myDuplex.on("readable", () => { console.log(myDuplex.read(1), "----"); }); setTimeout(() => { myDuplex.on("data", data => { console.log(data, "xxxx"); }); }, 3000); // <Buffer 31> ---- // <Buffer 32> xxxx // <Buffer 32> ---- // <Buffer 33> xxxx 複製代碼

若是 readabledata 兩種讀取方式都使用默認先經過 data 事件讀取,因此通常只選擇一個,不要同時使用,可讀流的特色是讀取數據被消耗掉後就丟失了(緩存區被清空),若是非要兩個都用能夠加一個定時器(絕對不要這樣寫)。網站


實現一個自定義轉化流 Transform

一、建立自定義可轉化流的類 MyTransform

轉化流的意思是便可以看成可讀流,又能夠看成可寫流,建立一個類名爲 MyTransform,並繼承 stream 中的 Transform 類,重寫 _transform 方法,該方法的參數和 _write 相同。ui

let { Transform } = require('stream'); // 建立自定義轉化流的類 class MyTransform extends Transform { // 重寫自定義的轉化流的 _transform 方法 _transform(chunk, encoding, callback)) { console.log(chunck.toString.toUpperCase()); callback(); this.push('123'); } } 複製代碼

在自定義轉化流的 _transform 方法中,讀取數據的 push 方法和 寫入數據的 callback 均可以使用。

二、驗證自定義轉化流

// demo.js let myTransForm = new MyTransform(); // 使用標準輸入 process.stdin.pipe(myTransForm).pipe(process.stdin); 複製代碼

打開命令行窗口執行 node demo.js,而後輸入 abc,會在命令窗口輸出 ABC123,其實轉換流先做爲一個可寫流被寫入到標準輸入中,而此時 stdin 的做用是讀流,即讀取用戶的輸入,讀取後轉換流做爲一個可讀流調用 pipe,將用戶輸入的信息經過標準輸出寫到命令行窗口,此時 stdout 的做用是寫流。

總結

自定義流最多見的種類在上面都已經涵蓋了,真正的在開發中用到的很少,若是須要寫一個自定義流應該比上面的複雜不少,本文主要目的是認識什麼是自定義流,並瞭解寫一個自定義流的基本套路。

 

最後,順便傳播一個好消息:

想上線本身的後臺系統或者作本身網站的,機會來了,騰訊雲現作活動,新手福利1000減750,雲服務器最低2折,雲服務器1核2G內存50G硬盤3年最低只要600元!戳此瞭解詳情


 

做者:PandaShen連接:https://juejin.im/post/5b5e2061e51d45339e7ed83c來源:掘金著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索