NodeJs系列之stream流

Stream流

stream 流分爲四種:

  1. Readable - 可讀操作。
  2. Writable - 可寫操作。
  3. Duplex - 可讀可寫操作.
  4. Transform - 操作被寫入數據,然後讀出結果。

所有的 Stream 對象都是 EventEmitter 的實例。常用的事件有:

data - 當有數據可讀時觸發。
end - 沒有更多的數據可讀時觸發。
error - 在接收和寫入過程中發生錯誤時觸發。
finish - 所有數據已被寫入到底層系統時觸發。

流的基本概念

流的英文stream,流(Stream)是一個抽象的數據接口,Node.js中很多對象都實現了流,流是EventEmitter對象的一個實例,會輸出以buffer爲單位的數據,或者能夠吸收數據的東西,它的本質就是讓數據流動起來。如下圖:
在這裏插入圖片描述

從圖可以直觀的看到,數據可以直接從源通過管道直接導入到目標中。這裏的stream不只是只有nodejs纔有,這是操作系統中基本操作方式。nodejs是提供了可以操作流的api。Linux中也有管道概念的命令 “|” 。

readfile、writefile文件讀寫對比
var fs = require("fs");
console.log("準備寫入文件");
fs.writeFile('input.txt', '我是通 過fs.writeFile 寫入文件的內容',  function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("數據寫入成功!");
   console.log("讀取寫入的數據!");
   //這裏讀取的數據data爲buffer類型數據,需要通過toString轉爲字符串
fs.readFile('input.txt', function (err, data) {
    if (err) {
       return console.error(err);
    }
    console.log("異步讀取文件數據: " + data.toString());
 });
});

上述代碼是使用fs庫中的readfile和writeFile方法異步讀寫文件 ,它是將整個文件一次性返回data,然後再去對數據進行操作或者輸出。這裏會存在一個問題,如果讀取的文件data特別大的時候,比如達到上百M的時候,在響應大量用戶併發請求的時候,程序可能會消耗大量的內存,這樣可能造成用戶連接緩慢的問題。併發過大的話,內存開銷也會比較大。Stream就完美的避開了這個問題,stream的原理是一邊讀取一邊返回。數據通過管道流動給客戶端,減輕了服務器的壓力。

Stream讀寫文件
var fs = require("fs");

// 創建一個可讀流
var readerStream = fs.createReadStream('input.txt');

// 創建一個可寫流
var writerStream = fs.createWriteStream('output.txt');

// 管道讀寫操作
// 讀取 input.txt 文件內容,並將內容寫入到 output.txt 文件中
readerStream.pipe(writerStream);

console.log("程序執行完畢");

上述代碼爲stream管道流對文件的讀寫,寫起來會比readfile方便一些,首先創建一個可讀數據流readStream,一個可寫數據流writeStream,然後直接通過pipe管道把數據流轉過去。這種使用stream的拷貝相比存文件的讀寫實現拷貝,性能要增加很多性能方面也會好很多,一邊讀取一邊寫入,數據像是通過一個管道流動了起來,這也就是stream流。

request和response

request和reponse一樣,都是stream對象,可以使用stream的特性,二者的區別在於request是source類型,而response是dest類型,數據的流向是從request 也就是source到 response的target。

Stream的弊端
  1. 通過管道(rs.pipe(ws))寫入文件的時候,不是進行append方式進行追加,而是直接覆蓋。
  2. 已經關閉的流不能重複使用,需要重新創建流。
  3. pipe 方法返回的是目標數據流,如 a.pipe(b) 返回的是 b,因此監聽事件的時候請注意你監聽的對象是否正確,例子上a.pipe(b) 這裏需要監聽的是b
    a.pipe(b).on(‘end’,function(){//這裏是b end })
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章