认识Node.js中流
認識Node.js中流
http://wwsun.github.io/posts/stream-in-nodejs.html?utm_source=tuicool&utm_medium=referral流是Node.js中一個非常重要的概念, 也是Node.js之所以適用于I/O密集型場景的重要原因之一。 流是Node.js移動數據的方式,流可以是可讀的和/或可寫的。在Node.js中很多模塊都使用到了流, 包括HTTP和fs模塊,本文將用盡可能簡單的方式為你介紹Node中流的概念。
流 Stream
事實上,流通常用于將程序連接在一起。流可以被讀和寫。被流連接在一起的程序通常很小,并且只專注于做一件事。
你可能經常在項目中使用Gulp來做項目的代碼構建,那么在使用過程中,你很可能碰到過類似下面的錯誤。 錯誤大概是這樣個的:
stream.js:94throw er; // Unhandled stream error in pipe.當初次碰到這種錯誤的時候,你可能和我一樣對流的概念毫無頭緒,好在我們可以借助Google來尋找答案。 一個最佳的開始是用Google搜索“node stream”之類的關鍵字, 從而我們可以獲得stream-adventure這類的課程學習。
在Node.js的文檔中,流(Stream)的官方定義如下:
流是一個抽象接口,在Node.js中它借助于多種對象實現。例如,一個對HTTP服務器的請求是一個流, 可以是stdout。流是可讀的,可寫的,或兩者兼備。所有的流都是EventEmitter的實例。
也就是說,Node.js中的很多模塊都是用到了流,例如http和fs模塊。例如在文件系統模塊(fs)中, 我們可以通過流來讀寫文件數據的實例。由于數據是流,這就意味著在完成文件讀取之前, 從收到最初幾個字節開始,就可以對數據動作。這是Node.js中的一個常見模式:
可讀流
const fs = require('fs'); const stream = fs.ReadStream('name.txt'); stream.setEncoding('utf-8'); stream.on('data', chunk => {console.log('read some data'); }); stream.on('close', () => {console.log('all the data is read'); });在上面的例子中,我們創建了一個可讀流,并在流讀取文件的過程中監聽事件,在收到新數據時觸發事件數據。 當文件讀取完成后觸發關閉事件。
此外,在流中,我們要負責按自己想要的方式使用數據,所以我們必須在數據事件接收到數據的時候處理它。 如果想要讀區所有數據,就必須將其拼接到一個變量中:
let data = '';stream.on('data', chunk => {data += chunk;console.log('read some data'); });如果讀取的文件很大,這就會觸發多個data事件,這就需要開發者可以在以接收到數據的時候就做一些事情, 而不是等到整個文件都讀取完成。
可寫流
顯然,我們也可以創建可寫流以便寫數據。這意味著,只要一段簡單的腳本,就可以使用流讀入文件然后寫入另一文件:
const fs = require('fs'); let readStream = fs.ReadStream('name.txt'); let writeStream = fs.WriteStream('out.txt'); readStream.setEncoding('utf-8'); readStream.on('data', chunk => {writeStream.write(chunk); }); readStream.on('close', () => {writeStream.end(); });在上面的例子中,當接收到data事件的時候,我們便將數據寫入到可寫流writeStream中,這非常的高效, 因為只要從可讀文件接收到數據事件,數據就會被寫入文件。尤其是對大文件而言,不會被阻塞。因此, 對于網絡和文件系統中移動數據而言,流的方式非常的高效。
通過管道連接流
本質上,流允許你講其他對象或程序連接在一起。你將某些輸入,然后讓它經過流, 將它傳遞到另一個程序中。我比較喜歡拿水管來做類比。將一組小型的管道(程序)連接在一起, 用于完成一些特定的任務。
管道(pipe)的概念很早就存在于Unix系統中,你可以通過這篇文章了解更多:Unix Pipelines
由于在輸入和輸出之間通過管道傳輸數據在Node.js中很常見,所以它也提供了連接兩個可讀和可寫流并在它們之間通過管道傳輸數據的方法。 例如:readStream.pipe(writeStream)。
pipe()方法會仔細處理事件,在需要的時候會暫停流并恢復流操作,所以除非需要對事件的發生有完全的控制權, 否則應該使用pipe()。
const fs = require('fs');// 指定讀取流,指向目標文件,編碼格式為utf-8 const file = fs.createReadStream('hello.txt', {encoding: 'utf-8'});// 流是EventEmitter的實例,我們可以為其添加事件 // 當打開文件時觸發open事件 file.on('open', function () {// 使用管道,將文件內容輸出到屏幕上// process對象也是一個EventEmitter實例this.pipe(process.stdout); });References
總結
以上是生活随笔為你收集整理的认识Node.js中流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 零基础开始学 Web 前端开发,有什么建
- 下一篇: 12 个非常有用的 JavaScript