stream(流)是什麼?
流(stream)在 Node.js 中是處理流資料的抽象介面(abstract interface)。 stream
模組提供了基礎的 API 。使用這些 API 可以很容易地來構建實現流介面的物件。
Node.js 提供了多種流物件。 例如, HTTP 請求 和 process.stdout
就都是流的例項。
流可以是可讀的、可寫的,或是可讀寫的。所有的流都是 EventEmitter
的例項。
流是一種抽象的資料結構。想象水流,當在水管中流動時,就可以從某個地方(例如自來水廠)源源不斷地到達另一個地方(比如你家的洗手池)。我們也可以把資料看成是資料流,比如你敲鍵盤的時候,就可以把每個字元依次連起來,看成字元流。
Node.js 中有四種基本的流型別:
- Readable - 可讀的流 (例如
fs.createReadStream()
). - Writable - 可寫的流 (例如
fs.createWriteStream()
). - Duplex - 可讀寫的流 (例如
net.Socket
). - Transform - 在讀寫過程中可以修改和變換資料的 Duplex 流 (例如
zlib.createDeflate()
).
所有使用 Node.js API 建立的流物件都只能操作 strings 和 Buffer
(或 Uint8Array
) 物件。但是,通過一些第三方流的實現,你依然能夠處理其它型別的 JavaScript 值 (除了 null
,它在流處理中有特殊意義)。 這些流被認為是工作在 “物件模式”(object mode)。
Readable (可讀流)
Readable 事件:
readable:事件將在流中有資料可供讀取時觸發。在某些情況下,為 'readable'
事件新增回撥將會導致一些資料被讀取到內部快取中。
data:事件會在流將資料傳遞給消費者時觸發。當流轉換到 flowing 模式時會觸發該事件。呼叫 readable.pipe()
, readable.resume()
方法,或為 'data'
事件新增回撥可以將流轉換到 flowing 模式。 'data'
事件也會在呼叫 readable.read()
方法並有資料返回時觸發。
end: 事件將在流中再沒有資料可供消費時觸發。
close: 當底層資源,如檔案,已關閉時觸出。
error:在接收資料中出錯是觸發。
Readable 方法:
read([size]):從流中讀資料.資料可以是String、Buffer、null(下面程式碼會有),當指定size,那麼只讀僅限於那個位元組數
setEncoding(encoding):設定read()請求讀取返回String時使用的編碼
pause():暫停從該物件發出的data事件
resume():恢復從該物件發出的data事件
建立一個Readable(可讀流):
let fs = require('fs');let path = require('path');
// 返回的是一個可讀流物件let rs = fs.createReadStream(path.join(__dirname,'1.txt'),{ flags:'r', // 檔案的操作是讀取操作 encoding:'utf8', // 預設是null null代表的是buffer autoClose:true, // 讀取完畢後自動關閉 highWaterMark:3,// 預設是64k 64*1024b 漢字是三個位元組 start:0, // 123 456 789 //end:9 // 包前又包後});// 預設情況下 不會將檔案中的內容輸出// 內部會先建立一個buffer先讀取3b
// 流動模式會瘋狂的觸發data事件,直到讀取完畢//rs.setEncoding('utf8');rs.on('open',function(){ console.log('檔案開啟了')});// newLisenterrs.on('data',function(data){ // 暫停模式 -> 流動模式 console.log(data); // rs.pause(); // 暫停方法 表示暫停讀取,暫停data事件觸發});
rs.on('readable',function(res){ console.log('有資料了'); });rs.on('error',function(err){ console.log(err);});rs.on('end',function(){ console.log('end')});rs.on('close',function(){ console.log('關閉')});複製程式碼
輸出的:
檔案開啟了 0123456789 有資料了 end 關閉複製程式碼
Writable (可寫流)
Writable事件:
write(chunk,[encoding],[callback]):將資料寫入流。chunk(資料塊)中包含要寫入的資料,encoding指定字串的編碼,callback指定當資料已經完全重新整理時執行的一個回撥函式。如果成功寫入,write()返回true.
end([chunk],[encoding],[callback]):與write()相同,它把Writable物件設為不再接受資料的狀態,併傳送finish事件。
Writable方法:
drain:在write()呼叫返回false後,當準備好開始寫更多資料時,發出此事件通知監視器。
finish:當end()在Writable物件上呼叫,所以資料被重新整理,並不會有更多的資料被接受時觸發
建立一個Writable:
let fs = require('fs');let path = require('path');
// 寫的時候檔案不存在 會建立檔案let ws = fs.createWriteStream(path.join(__dirname,'1.txt'),{ highWaterMark:3, autoClose:true, flags:'w', encoding:'utf8', mode:0o666, start:0,});// 寫內容的時候 必須是字串或者bufferfor(var i = 0;i<4;i++){ let flag = ws.write(i+''); // 第一次寫一個字元 console.log(flag)}ws.on('drain',function(){ console.log('drain')});複製程式碼
控制檯列印:
true true false falsedrain1.txt 的內容是: 0123複製程式碼