stream pipe的原理及簡(jiǎn)化源碼分析

前言

在編寫代碼時(shí)锰茉,我們應(yīng)該有一些方法將程序像連接水管一樣連接起來(lái) -- 當(dāng)我們需要獲取一些數(shù)據(jù)時(shí),可以去通過(guò)"擰"其他的部分來(lái)達(dá)到目的。這也應(yīng)該是IO應(yīng)有的方式珍昨。 -- Doug McIlroy. October 11, 1964

本質(zhì)上來(lái)說(shuō)双揪,編碼就是對(duì)數(shù)據(jù)的讀取动羽,處理最后返回結(jié)果,數(shù)據(jù)在一個(gè)程序又一個(gè)程序中不斷傳遞渔期。理想情況下运吓,數(shù)據(jù)的傳遞應(yīng)該是不停滯的,但是現(xiàn)實(shí)情況中因?yàn)橹T如單個(gè)數(shù)據(jù)過(guò)大疯趟,內(nèi)存較小拘哨,IO處理較慢等客觀原因使數(shù)據(jù)不能流暢的流動(dòng)起來(lái)。這時(shí)我們就需要一種方法去將數(shù)據(jù)拆分成一小塊一小塊的數(shù)據(jù)(chunks),流水一樣的讀取處理寫入迅办。這種方法便是流(stream)宅静,nodejs中的流主要分為以下四種:

  • Readable(可讀流)
  • Writable(可寫流)
  • Duplex(可讀寫流)
  • Transform (變換流)

而所有的流都有一種公有方法,它會(huì)像管道一樣處理流的數(shù)據(jù)站欺,這便是pipe,下面一張大神制作的圖很好的演示了這個(gè)過(guò)程:

Markdown

正文

pipe期望的使用方式

pipe函數(shù)需要將源頭src并將數(shù)據(jù)輸出到一個(gè)可寫的流dst中:

src.pipe(dst)

pipe將會(huì)返回dst,所以我們希望可以鏈?zhǔn)秸{(diào)用將多個(gè)流用管道連接起來(lái):

a.pipe(b).pipe(c).pipe(d)

pipe的簡(jiǎn)化源碼分析

為了實(shí)現(xiàn)以上期望的使用方式姨夹,我們將Nodejs源碼簡(jiǎn)化一下看是怎樣實(shí)現(xiàn)的

stream.prototype.pipe = function(dest, options) {
  this.on('data', (chunk) => {
    if (dest.writable) {
      if (false === dest.write(chunk) && this.pause) {
        this.pause();
      }
    }
  });
  dest.on('drain', () => {
    this.resume();
  });
  dest.emit('pipe', this);
  
  return dest;
};

以上代碼主要做了4件事:

  • 可讀流監(jiān)聽data事件
    1)首先判斷dest.Writable,當(dāng)寫完時(shí)會(huì)賦值為false
    2)此時(shí)如果消費(fèi)者消費(fèi)速度慢矾策,這時(shí)產(chǎn)生了一個(gè)現(xiàn)象磷账,叫做背壓。背壓?jiǎn)栴}即是外部的生產(chǎn)者和消費(fèi)者速度差造成的贾虽,此時(shí)我們需要暫停寫入.pause()
  • 可寫流監(jiān)聽drain事件
    1)消費(fèi)者完成消費(fèi)逃糟,可以觸發(fā)drain事件,此時(shí)我們可以繼續(xù)向流中寫入數(shù)據(jù)蓬豁。執(zhí)行.resume()
  • 觸發(fā)pipe事件绰咽,通知有流寫入
  • 返回dest流,可以進(jìn)行鏈?zhǔn)秸{(diào)用

小記

簡(jiǎn)單的梳理了下stream pipe的原理和實(shí)現(xiàn)方式地粪。在現(xiàn)實(shí)應(yīng)用中諸如gulp取募,Browserify等工作流工具都使用了pipe。而stream更是應(yīng)用廣泛蟆技,文件玩敏、http斗忌、打包壓縮甚至console等都是用流實(shí)現(xiàn)的。

參考資料
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旺聚,一起剝皮案震驚了整個(gè)濱河市织阳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砰粹,老刑警劉巖唧躲,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異伸眶,居然都是意外死亡惊窖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門厘贼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)界酒,“玉大人,你說(shuō)我怎么就攤上這事嘴秸』傩溃” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵岳掐,是天一觀的道長(zhǎng)凭疮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)串述,這世上最難降的妖魔是什么执解? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮纲酗,結(jié)果婚禮上衰腌,老公的妹妹穿的比我還像新娘。我一直安慰自己觅赊,他們只是感情好右蕊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吮螺,像睡著了一般饶囚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鸠补,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天萝风,我揣著相機(jī)與錄音,去河邊找鬼紫岩。 笑死闹丐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的被因。 我是一名探鬼主播卿拴,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梨与!你這毒婦竟也來(lái)了堕花?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤粥鞋,失蹤者是張志新(化名)和其女友劉穎缘挽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呻粹,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壕曼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了等浊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腮郊。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖筹燕,靈堂內(nèi)的尸體忽然破棺而出轧飞,到底是詐尸還是另有隱情,我是刑警寧澤撒踪,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布过咬,位于F島的核電站,受9級(jí)特大地震影響制妄,放射性物質(zhì)發(fā)生泄漏掸绞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一耕捞、第九天 我趴在偏房一處隱蔽的房頂上張望衔掸。 院中可真熱鬧,春花似錦砸脊、人聲如沸具篇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)驱显。三九已至,卻和暖如春瞳抓,著一層夾襖步出監(jiān)牢的瞬間埃疫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工孩哑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栓霜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓横蜒,卻偏偏與公主長(zhǎng)得像胳蛮,于是被迫代替她去往敵國(guó)和親销凑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • gulpjs是一個(gè)前端構(gòu)建工具仅炊,與gruntjs相比斗幼,gulpjs無(wú)需寫一大堆繁雜的配置參數(shù),API也非常簡(jiǎn)單抚垄,學(xué)...
    井皮皮閱讀 1,296評(píng)論 0 10
  • stream 流是一個(gè)抽象接口蜕窿,在 Node 里被不同的對(duì)象實(shí)現(xiàn)。例如 request to an HTTP se...
    明明三省閱讀 3,404評(píng)論 1 10
  • 為什么應(yīng)該使用流 你可能看過(guò)這樣的代碼呆馁。 這段代碼中桐经,服務(wù)器每收到一次請(qǐng)求,就會(huì)先把data.txt讀入到內(nèi)存中浙滤,...
    饑人谷_xxxxx閱讀 10,817評(píng)論 1 12
  • http://www.reibang.com/p/81b032672223 為什么應(yīng)該使用流 你可能看過(guò)這樣的代...
    流動(dòng)碼文閱讀 265評(píng)論 0 1
  • 我低著頭小心追尋你的印記瓷叫, 卻被濕潤(rùn)的泥土殷勤挽留屯吊, 呼吸里牽引著清爽的靈動(dòng)氣息, 惹人心悸摹菠。 云塊被割分得很工整...
    IMEJE閱讀 199評(píng)論 1 2