亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Nodejs中可寫流如何使用

發布時間:2020-11-24 11:06:08 來源:億速云 閱讀:177 作者:小新 欄目:web開發

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

什么是可寫流

可寫流是對數據流向設備的抽象,用來消費上游流過來的數據,通過可寫流程序可以把數據寫入設備,常見的是本地磁盤文件或者 TCP、HTTP 等網絡響應。

看一個之前用過的例子

process.stdin.pipe(process.stdout);

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

可寫流使用

調用可寫流實例的 **write() **方法就可以把數據寫入可寫流

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);
});

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

write() 方法有三個參數

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

自定義可寫流

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

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

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

const Writable = require('stream').Writable

class OutputStream extends Writable {
    _write(chunk, enc, done) {
        // 轉大寫之后寫入標準輸出設備
        process.stdout.write(chunk.toString().toUpperCase());
        // 此處不嚴謹,應該是監聽寫完之后才調用 done
        process.nextTick(done);
    }
}

module.exports = OutputStream;

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

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

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

實例化可寫流

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

  • objectMode
  • highWaterMark
  • decodeStrings

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

事件

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

  • pipe 當可讀流調用 pipe() 方法向可寫流傳輸數據的時候會觸發可寫流的 pipe 事件
  • unpipe 當可讀流調用 unpipe() 方法移除數據傳遞的時候會觸發可寫流的 unpipe 事件

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

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

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

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

finish 當調用 writable.end() 方法,并且所有數據都被寫入底層后會觸發 finish 事件

同樣出現錯誤后會觸發 error 事件

back pressure

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

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

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

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

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

class OutputStream extends Writable {
    _write(chunk, enc, done) {
        // 轉大寫之后寫入標準輸出設備
        process.stdout.write(chunk.toString().toUpperCase());
        // 故意延緩通知繼續傳遞數據的時間,造成寫入速度慢的現象
        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(); // 暫停數據讀取
    }
});

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

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

  • duplex
  • transform

感謝你能夠認真閱讀完這篇文章,希望小編分享Nodejs中可寫流如何使用內容對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宜兰县| 怀宁县| 松阳县| 定安县| 论坛| 石渠县| 丰顺县| 呼玛县| 家居| 淮滨县| 商洛市| 泗洪县| 大足县| 辽宁省| 宁都县| 济源市| 芦山县| 亚东县| 隆林| 平陆县| 邮箱| 额济纳旗| 乌拉特中旗| 沁阳市| 仁化县| 郧西县| 红安县| 慈溪市| 南投县| 独山县| 吉安县| 深泽县| 萨迦县| 上饶市| 化隆| 大悟县| 百色市| 肇源县| 资讯| 陇南市| 湖北省|