按照官方的定義node
流(stream)是 Node.js 中處理流式數據的抽象接口。stream模塊用於構建實現了流接口的對象。
咱們通常是直接使用node提供的流對象,例如在服務器請求、文件模塊中使用。服務器
data事件在可讀流將數據傳給消費者後觸發,特別注意的是,添加了該事件的流會自動切換爲流動模式, end事件在當流中沒有數據可供消費時觸發:ui
const stream = fs.createReadStream('./file.txt') // 默認靜止態 let chunks = [] stream.on("data", (chunk) => { // 變成流動態 chunks.push(chunk) }) stream.on("end", () => { constcontent = Buffer.concat(chunks).toString() console.log(content) })
readable事件代表流有新的動態:要麼有新的數據,要麼到達流的盡頭。下面是讀取文件的例子:code
const stream = fs.createReadStream('./file.txt') let chunks = [] stream.on("readable", () => { // stream中無數據也會觸發readable, 此時read方法獲得null console.log('觸發readable'); let data; while (data = stream.read(1024)) { chunks.push(data) console.log('讀取數據', data); } }) stream.on("end", () => { const content = Buffer.concat(chunks).toString(); console.log(content) })
使用readable會使流的狀態變成靜止態,即便監聽了data事件。在調用read方法且有返回數據時會觸發data事件。上面代碼中,read方法讀取內部緩衝中的數據,若是不指定size參數,則是讀取內部緩衝中的全部數據,注意不是流中的全部數據,不指定size的話也就不必使用while循環了,直接一次性讀取,while循環代碼塊可變爲:server
data = stream.read() data && chunks.push(data) console.log('讀取數據', data);
根據運行結果,read方法將緩衝區數據讀完後會觸發readable事件,也就是當read()返回null後觸發。對象
定義見官方文檔,下面例子使用pipe響應http請求接口
const http = require('http') const fs = require('fs') const server = http.createServer() server.on('request', (request, response) => { const stream = fs.createReadStream('./file.txt') stream.pipe(response) }) server.listen(8888)
數據流會被自動管理,因此即便可讀流更快,目標可寫流也不會超負荷。
上面的例子能夠用data事件改寫:事件
//.... server.on('request', (request, response) => { const stream = fs.createReadStream('./file.txt') stream.on("data", (chunk) => { response.write(chunk) }) stream.on("end", () => { response.end() // 使用pipe的話默認會在可讀流觸發end事件後調用end()結束寫入 }) }) //...
另外pipe支持鏈式操做: a.pipe(b).pipe(c)
等價於 a.pipe(b); a.pipe(c)
ip
可讀流流動態和靜止態的切換,改變data事件是否觸發文檔
這兩個事件是對於可寫流的
若是可寫流調用write() 返回 false,說明寫的太快了,不能再往裏面寫了。當能夠繼續寫入數據到流時會觸發 'drain' 事件。
finish事件在調用end() 且緩衝數據都已傳給底層系統以後觸發。
上面的例子已有涉及到。write是寫入數據到可寫流,end代表寫入完畢,之久不能再調用write了