摘要:的源碼僅僅就多行,本質上就是對于原生的流進行的封裝,先來看下。是一個雙工流,既可讀,也可寫,但是與還是有著一些區(qū)別,的寫和讀可以說是沒有任何的關聯(lián),是兩個緩沖區(qū)和管道互補干擾,而將其輸入和輸出是存在相互關聯(lián)的,中間做了處理。
寫在前面
through2經常被用于處理node的stream,假如使用過gulp的話,對于這個包一定不會陌生,如:
gulp.task("rewrite", () => { return gulp.src("./through/enter.txt") .pipe(through2.obj(function(chunk, enc, callback) { const { contents } = chunk; for (var i = 0; i < contents.length; i++) { if (contents[i] === 97) { contents[i] = 122; } } chunk.contents = contents; this.push(chunk); callback(); })) .pipe(gulp.dest("./dist")); });
這里將文件中所有的字符a轉換為字符z,在寫gulp插件時一定會應用到這個包,下面就來窺探一下這個使用率非常高的包。
Transform streamthrough2的源碼僅僅就100多行,本質上就是對于node原生的transform流進行的封裝,先來看下Transform stream。Transform是一個雙工流,既可讀,也可寫,但是與Duplex還是有著一些區(qū)別,Duplex的寫和讀可以說是沒有任何的關聯(lián),是兩個緩沖區(qū)和管道互補干擾,而Transform將其輸入和輸出是存在相互關聯(lián)的,中間做了處理。具體差別可以參考下面圖片對比:
Duplex stream:
Transform stream:
Transform stream的兩個緩存區(qū)相互關聯(lián),對于每個緩沖區(qū)來說,highWaterMark為閾值,超過閾值后,將會停止讀或者寫操作,如:
let i = 0; const readable = Readable({ highWaterMark: 2, read: function () { var data = i < 26 ? String.fromCharCode(i++ + 97) : null; console.log("push", data); this.push(data); } }); const transform = Transform({ highWaterMark: 2, transform: function (buf, enc, next) { console.log("transform", buf.toString()); next(null, buf); } }) readable.pipe(transform);
stream流向為:
由于閾值為2,所以只能push到f,這時readable的緩存區(qū)已滿,transform的讀緩存區(qū)和寫緩存區(qū)已經滿了(由于transform的兩個緩存區(qū)的閾值為2,所以寫緩存區(qū)在寫入b之后就已經滿了,后續(xù)不能繼續(xù)寫入),全部滿之后,自然停止了讀取,最終e,f存在A中,c,d存在B中,a,b存在C中,想要解決很簡單,在添加一個流向就可以:
readable.pipe(transform).pipe(process.stdout);through2源碼
在了解Transform stream之后,through2的源碼非常的簡單,就是對于其的一層封裝,暴露出三個api(through2,through2.obj,through2.ctor)而且三者接收的參數一致,因為都是由一個工廠方法創(chuàng)造出的:
function through2 (construct) { return function (options, transform, flush) { // 做了一些參數整理 if (typeof options == "function") { flush = transform transform = options options = {} } if (typeof transform != "function") transform = noop if (typeof flush != "function") flush = null return construct(options, transform, flush) } }
來看一下through2對于Transform stream的再加工,也就是源碼中的DestroyableTransform,與其名字一樣,就是一個替我們實現好了destory方法的Transform stream:
DestroyableTransform.prototype.destroy = function(err) { if (this._destroyed) return this._destroyed = true var self = this // 觸發(fā)destory后,close掉流 process.nextTick(function() { if (err) self.emit("error", err) self.emit("close") }) }
through2與through2.obj全部是創(chuàng)造出一個再加工后的Transform,區(qū)別如下:
后者開啟了對象模式(objectMode屬性為true),寫入的參數不僅僅限制在string or uint8Array
后者降低了閾值(highWaterMark為16,而不是默認的16kb),這樣做的原因,是為了和node的默認保持一致,具體可以參見這里
through2.ctor可以用來再次定制,其返回的是一個構造函數,用法可以參考下面:
const Tran = through.ctor(function(chunk, enc, callback) { console.log("transform", chunk.toString()); callback(null, chunk); }); const transform = new Tran();寫在最后
stream在node中有著非常廣泛的應用,但是它使用起來卻不是那么友好,throgh2的出現可以減少使用上的麻煩,其原理也非常的簡單;以上內容均為本人理解,如有錯誤還請指出,不勝感激~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89349.html
摘要:地址采用流模式讀取文件,每次讀取一行數據對流的二次封裝,更加易于使用普通用法等同于可以使號或者號參數每次流傳完可以和一樣做一些數據處理將文件中的全部替換為輸出到完事寫入完成對于需要相同處理過程的數據可以采用該方法創(chuàng)建一個構造函數完事 [github地址:https://github.com/ABCDdouyae...] csv2 采用流模式讀取.csv文件,每次讀取一行數據 throu...
摘要:地址采用流模式讀取文件,每次讀取一行數據對流的二次封裝,更加易于使用普通用法等同于可以使號或者號參數每次流傳完可以和一樣做一些數據處理將文件中的全部替換為輸出到完事寫入完成對于需要相同處理過程的數據可以采用該方法創(chuàng)建一個構造函數完事 [github地址:https://github.com/ABCDdouyae...] csv2 采用流模式讀取.csv文件,每次讀取一行數據 throu...
摘要:地址采用流模式讀取文件,每次讀取一行數據對流的二次封裝,更加易于使用普通用法等同于可以使號或者號參數每次流傳完可以和一樣做一些數據處理將文件中的全部替換為輸出到完事寫入完成對于需要相同處理過程的數據可以采用該方法創(chuàng)建一個構造函數完事 [github地址:https://github.com/ABCDdouyae...] csv2 采用流模式讀取.csv文件,每次讀取一行數據 throu...
摘要:優(yōu)化性能這里有個有意思的地方。在多個參數的情況下。無則跳過,支持覆蓋不可變。與原先不同的是,這里使用了一份初始化的對象引用來作為容器承載其余沒有不同 through2 本質上是一種transform的流 被封裝更好地操作流 var Transform = require(readable-stream/transform) , inherits = require(util).i...
閱讀 2943·2023-04-25 19:20
閱讀 786·2021-11-24 09:38
閱讀 2040·2021-09-26 09:55
閱讀 2430·2021-09-02 15:11
閱讀 2015·2019-08-30 15:55
閱讀 3610·2019-08-30 15:54
閱讀 3148·2019-08-30 14:03
閱讀 2962·2019-08-29 17:11