成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Nodejs中可寫流如何使用

這篇文章主要介紹了Nodejs中可寫流如何使用,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

章貢網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站開發(fā)等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)公司于2013年創(chuàng)立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。

什么是可寫流

可寫流是對數(shù)據(jù)流向設(shè)備的抽象,用來消費上游流過來的數(shù)據(jù),通過可寫流程序可以把數(shù)據(jù)寫入設(shè)備,常見的是本地磁盤文件或者 TCP、HTTP 等網(wǎng)絡(luò)響應(yīng)。

看一個之前用過的例子

process.stdin.pipe(process.stdout);

*process.stdout* 是一個可寫流,程序把可讀流 process.stdin 傳過來的數(shù)據(jù)寫入的標準輸出設(shè)備。在了解了可讀流的基礎(chǔ)上理解可寫流非常簡單,流就是有方向的數(shù)據(jù),其中可讀流是數(shù)據(jù)源,可寫流是目的地,中間的管道環(huán)節(jié)是雙向流。

可寫流使用

調(diào)用可寫流實例的 **write() **方法就可以把數(shù)據(jù)寫入可寫流

const fs = require('fs');
const rs = fs.createReadStream('./w.js');
const ws = fs.createWriteStream('./copy.js');

rs.setEncoding('utf-8');
rs.on('data', chunk => {
  ws.write(chunk);
});

前面提到過監(jiān)聽了可讀流的 data 事件就會使可讀流進入流動模式,我們在回調(diào)事件里調(diào)用了可寫流的 write() 方法,這樣數(shù)據(jù)就被寫入了可寫流抽象的設(shè)備中,也就是當前目錄下的 copy.js 文件。

write() 方法有三個參數(shù)

  • chunk{String| Buffer},表示要寫入的數(shù)據(jù)
  • encoding當寫入的數(shù)據(jù)是字符串的時候可以設(shè)置編碼
  • callback數(shù)據(jù)被寫入之后的回調(diào)函數(shù)

自定義可寫流

和自定義可讀流類似,簡單的自定義可寫流只需要兩步

  1. 繼承 stream 模塊的 Writable
  2. 實現(xiàn) _write()方法

我們來實現(xiàn)一個簡單的可寫流,把傳入可寫流的數(shù)據(jù)轉(zhuǎn)成大寫之后輸出到標準輸出設(shè)備(比較好的例子可能是寫入本地磁盤文件,但涉及過多的 fs 操作,比較麻煩,偷個懶。寫入標準輸出設(shè)備也是一種寫入行為)

const Writable = require('stream').Writable

class OutputStream extends Writable {
    _write(chunk, enc, done) {
        // 轉(zhuǎn)大寫之后寫入標準輸出設(shè)備
        process.stdout.write(chunk.toString().toUpperCase());
        // 此處不嚴謹,應(yīng)該是監(jiān)聽寫完之后才調(diào)用 done
        process.nextTick(done);
    }
}

module.exports = OutputStream;

和最終可寫流暴露出來的 write() 方法一樣, _write() 方法有三個參數(shù),作用類似

  • chunk寫入的數(shù)據(jù),大部分時候是 buffer,除非 decodeStrings 被設(shè)置為 false
  • encoding如果數(shù)據(jù)是字符串,可以設(shè)置編碼,buffer 或者 object 模式會忽略
  • callback數(shù)據(jù)寫入后的回調(diào)函數(shù),可以通知流傳入下一個數(shù)據(jù);當出現(xiàn)錯誤的時候也可以設(shè)置一個 error 參數(shù)

當然其實還有一個 _writev() 方法可以實現(xiàn),這個方法僅被滯留的寫入隊列調(diào)用,可以不實現(xiàn)。

實例化可寫流

有了可寫流的類之后我們可以實例化使用了,實例化可寫流的時候有幾個 option 可選,了解一下可以幫助我們理解后面要用的知識

  • objectMode
  • highWaterMark
  • decodeStrings

這樣我們就更清楚的知道 _write() 方法傳入的參數(shù)的含義了,而且對后面介紹 back pressure 機制的理解很有幫助。

事件

和可讀流一樣,可寫流也有幾個常用的事件,有了可讀流的基礎(chǔ),理解起來比較簡單

  • pipe當可讀流調(diào)用 pipe() 方法向可寫流傳輸數(shù)據(jù)的時候會觸發(fā)可寫流的 pipe 事件
  • unpipe當可讀流調(diào)用 unpipe() 方法移除數(shù)據(jù)傳遞的時候會觸發(fā)可寫流的 unpipe 事件

這兩個事件用于通知可寫流數(shù)據(jù)將要到來和將要被切斷,在通常情況下使用的很少。

writeable.write() 方法是有一個 bool 的返回值的,前面提到了 highWaterMark,當要求寫入的數(shù)據(jù)大于可寫流的 highWaterMark 的時候,數(shù)據(jù)不會被一次寫入,有一部分數(shù)據(jù)被滯留,這時候 writeable.write() 就會返回 false,如果可以處理完就會返回 true

drain當之前存在滯留數(shù)據(jù),也就是 writeable.write() 返回過 false,經(jīng)過一段時間的消化,處理完了積壓數(shù)據(jù),可以繼續(xù)寫入新數(shù)據(jù)的時候觸發(fā)(drain 的本意即為排水、枯竭,挺形象的)

除了 write() 方法可寫流還有一個常用的方法 end(),參數(shù)和 write() 方法相同,但也可以不傳入?yún)?shù),表示沒有其它數(shù)據(jù)需要寫入,可寫流可以關(guān)閉了。

finish當調(diào)用 writable.end() 方法,并且所有數(shù)據(jù)都被寫入底層后會觸發(fā) finish 事件

同樣出現(xiàn)錯誤后會觸發(fā) error事件

back pressure

了解了這些事件,結(jié)合上之前提到的可讀流的一些知識,我們就能探討一些有意思的話題了。在最開始我們提到過用流相對于直接操作文件的好處之一是不會把內(nèi)存壓爆,那么流是怎么做到的呢?

最開始我們可能會想到因為流不是一次性把所有數(shù)據(jù)載入內(nèi)存處理,而是一邊讀一邊寫。但我們知道一般讀取的速度會遠遠快于寫入的速度,那么 pipe()  方法是怎么做到供需平衡的呢?

回憶一些基礎(chǔ)知識,我們自己來實現(xiàn)一下 pipe() 方法的核心原理

  1. 可讀流有流動和暫停兩種模式,可以通過 **pause() resume() **方法切換
  2. 可寫流的 **write() **方法會返回是否能處理當前的數(shù)據(jù),每次可以處理多少是 hignWatermark決定的
  3. 當可寫流處理完了積壓數(shù)據(jù)會觸發(fā) drain事件

我們可以利用這三點來做到數(shù)據(jù)讀取和寫入的同步,還是使用之前的例子,但為了使消費速度降下來,我們各一秒再通知完成

class OutputStream extends Writable {
    _write(chunk, enc, done) {
        // 轉(zhuǎn)大寫之后寫入標準輸出設(shè)備
        process.stdout.write(chunk.toString().toUpperCase());
        // 故意延緩通知繼續(xù)傳遞數(shù)據(jù)的時間,造成寫入速度慢的現(xiàn)象
        setTimeout(done, 1000);
    }
}

我們使用一下自定義的兩個類

const RandomNumberStream = require('./RandomNumberStream');
const OutputStream = require('./OutputStream');

const rns = new RandomNumberStream(100);
const os = new OutputStream({
    highWaterMark: 8 // 把水位降低,默認16k還是挺大的
});

rns.on('data', chunk => {
    // 當待處理隊列大于 highWaterMark 時返回 false
    if (os.write(chunk) === false) { 
        console.log('pause');
        rns.pause(); // 暫停數(shù)據(jù)讀取
    }
});

// 當待處理隊列小于 highWaterMark 時觸發(fā) drain 事件
os.on('drain', () => {
    console.log('drain')
    rns.resume(); // 恢復數(shù)據(jù)讀取
});

結(jié)合前面的三點和注釋很容易看懂上面代碼,這就是 pipe() 方法起作用的核心原理。數(shù)據(jù)的來源的去向我們有了大概了解,后面可以開始介紹數(shù)據(jù)的加工

  • duplex
  • transform

感謝你能夠認真閱讀完這篇文章,希望小編分享Nodejs中可寫流如何使用內(nèi)容對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問題就找創(chuàng)新互聯(lián),詳細的解決方法等著你來學習!

新聞標題:Nodejs中可寫流如何使用
本文URL:http://jinyejixie.com/article38/ijcpsp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷微信公眾號、虛擬主機、建站公司、自適應(yīng)網(wǎng)站品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
兰州市| 毕节市| 巧家县| 赫章县| 客服| 潞西市| 江门市| 渝北区| 梁平县| 威宁| 云安县| 玉龙| 德昌县| 岳阳市| 济南市| 东宁县| 伽师县| 盐津县| 开化县| 东丽区| 酒泉市| 福鼎市| 共和县| 界首市| 镇沅| 含山县| 同仁县| 澳门| 齐齐哈尔市| 井陉县| 利川市| 刚察县| 盖州市| 舟山市| 九江县| 渭南市| 乃东县| 车险| 澄城县| 柯坪县| 独山县|