Nodejs中stream流模塊怎么樣

這篇文章將為大家詳細講解有關Nodejs中stream流模塊怎么樣,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯是一家專注于成都做網站、成都網站建設與策劃設計,溪湖網站建設哪家好?創(chuàng)新互聯做網站,專注于網站建設10余年,網設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:溪湖等地區(qū)。溪湖做網站價格咨詢:18982081108

stream流模塊,是Node中非常核心的一個模塊,其它模塊如fs、http等都基于流stream模塊的實例。

而對于大多前端小白在剛入門Node的學習過程中,對于流的概念及使用還是不太好清晰的理解,因為在前端的工作中似乎很少有過關于"流"處理相關的應用。

1. 流,是什么?

單純“流”這個字,我們很容易產生水流,流動等的概念。

官方定義:流,是用于在 Node.js 中處理流數據的抽象接口

從官方的定義中,我們可以看出:

  • 流,是Node提供的一種處理數據的工具

  • 流,是Node中的一種抽象接口

準確的理解,流,可以理解為數據流,它是一種用來傳輸數據的手段,在一個應用程序中,流,是一種有序的,有起點和終點的數據流。

造成我們對stream流不太好的理解的主要原因就是,它是一種抽象的概念。

2. 流,的具體使用場景

為了讓我們能夠清楚的理解stream模塊,我們首先來以具體的應用場景來說明stream模塊有哪些實際應用之處。

stream流,在Node中主要應用在大量數據處理的需求上,如fs對大文件的讀取和寫入、http請求響應、文件的壓縮、數據的加密/解密等應用。

Nodejs中stream流模塊怎么樣

我們以上面的圖片說明流的使用,水桶可以理解為數據源,水池可以理解為數據目標,中間連接的管道,我們可以理解為數據流,通過數據流管道,數據從數據源流向數據目標。

3. 流的分類

在Node中,流被分為4類:可讀流,可寫流,雙工流,轉換流。

  • Writable: 可以寫入數據的流

  • Readable: 可以從中讀取數據的流

  • Duplex: ReadableWritable 的流

  • Transform: 可以在寫入和讀取數據時修改或轉換數據的 Duplex

所有的流都是 EventEmitter 的實例。即我們可以通過事件機制監(jiān)聽數據流的變化。

4. 數據模式和緩存區(qū)

在深入學習4類流的具體使用之前,我們需要理解兩個概念數據模式緩存區(qū),有助于我們在接下來流的學習中更好的理解。

4.1 數據模式

Node.js API 創(chuàng)建的所有流都只對字符串Buffer(或 Uint8Array)對象進行操作。

4.2 緩存區(qū)

WritableReadable 流都將數據存儲在內部緩沖區(qū)(buffer)中。

可緩沖的數據量取決于傳給流的構造函數的 highWaterMark 選項, 對于普通的流,highWaterMark 選項指定字節(jié)的總數;對于在對象模式下操作的流,highWaterMark選項指定對象的總數。

highWaterMark 選項是閾值,而不是限制:它規(guī)定了流在停止請求更多數據之前緩沖的數據量。

當實現調用 stream.push(chunk) 時,數據緩存在 Readable 流中。 如果流的消費者沒有調用 stream.read(),則數據會一直駐留在內部隊列中,直到被消費。

一旦內部讀取緩沖區(qū)的總大小達到 highWaterMark 指定的閾值,則流將暫時停止從底層資源讀取數據,直到可以消費當前緩沖的數據

當重復調用 writable.write(chunk) 方法時,數據會緩存在 Writable 流中。

5. 可讀流

5.1 流讀取的流動與暫停

Readable 流以兩種模式之一有效地運行:流動和暫停。

  • 流動模式:從系統(tǒng)底層讀取數據并push()到緩存區(qū),達到highWaterMark后 push() 會返回 false,資源停止流向緩存區(qū),并觸發(fā)data事件消費數據。

  • 暫停模式:所有的Readable流都是以Paused暫停模式開始,必須顯式調用stream.read()方法來從流中讀取數據。每一次數據達到緩存區(qū)都會觸發(fā)一次 readable 事件,也就是每一次 push() 都會觸發(fā) readable。

  • 暫停模式切換到流動模式的方式:

    • 添加data事件句柄

    • 調用stream.resume()方法

    • 調用stream.pipe()方法將數據發(fā)送到 Writable

  • 流動模式切換到暫停模式的方式:

    • 如果沒有管道目標,則通過調用 stream.pause() 方法。

    • 如果有管道目標,則刪除所有管道目標。 可以通過調用 stream.unpipe()方法刪除多個管道目標。

5.2 可讀流常用示例

import path from 'path';
import fs, { read } from 'fs';

const filePath = path.join(path.resolve(), 'files', 'text.txt');

const readable = fs.createReadStream(filePath);
// 如果使用 readable.setEncoding() 方法為流指定了默認編碼,則監(jiān)聽器回調將把數據塊作為字符串傳入;否則數據將作為 Buffer 傳入。
readable.setEncoding('utf8');
let str = '';

readable.on('open', (fd) => {
  console.log('開始讀取文件')
})
// 每當流將數據塊的所有權移交給消費者時,則會觸發(fā) 'data' 事件
readable.on('data', (data) => {
  str += data;
  console.log('讀取到數據')
})
// 方法將導致處于流動模式的流停止觸發(fā) 'data' 事件,切換到暫停模式。 任何可用的數據都將保留在內部緩沖區(qū)中。
readable.pause();
// 方法使被顯式暫停的 Readable 流恢復觸發(fā) 'data' 事件,將流切換到流動模式。
readable.resume();
// 當調用 stream.pause() 并且 readableFlowing 不是 false 時,則會觸發(fā) 'pause' 事件。
readable.on('pause', () => {
  console.log('讀取暫停')
})
// 當調用 stream.resume() 并且 readableFlowing 不是 true 時,則會觸發(fā) 'resume' 事件。
readable.on('resume', () => {
  console.log('重新流動')
})
// 當流中沒有更多數據可供消費時,則會觸發(fā) 'end' 事件。
readable.on('end', () => {
  console.log('文件讀取完畢');
})
// 當流及其任何底層資源(例如文件描述符)已關閉時,則會觸發(fā) 'close' 事件。
readable.on('close', () => {
  console.log('關閉文件讀取')
})
// 將 destWritable 流綁定到 readable,使其自動切換到流動模式并將其所有數據推送到綁定的 Writable。 數據流將被自動管理
readable.pipe(destWriteable)
// 如果底層流由于底層內部故障而無法生成數據,或者當流實現嘗試推送無效數據塊時,可能會發(fā)生這種情況。
readable.on('error', (err) => {
  console.log(err)
  console.log('文件讀取發(fā)生錯誤')
})

6. 可寫流

6.1 可寫流的流動與暫停

writeable流 與 readable流 是比較相似的,數據流過來的時候,會直接寫入到緩存區(qū),當寫入速度比較緩慢或者寫入暫停時,數據流會在緩存區(qū)緩存起來;

當生產者寫入速度過快,把隊列池裝滿了之后,就會出現「背壓」,這個時候是需要告訴生產者暫停生產的,當隊列釋放之后,writable流 會給生產者發(fā)送一個 drain 消息,讓它恢復生產。

6.2 可寫流示例

import path from 'path';
import fs, { read } from 'fs';

const filePath = path.join(path.resolve(), 'files', 'text.txt');
const copyFile = path.join(path.resolve(), 'files', 'copy.txt');

let str = '';
// 創(chuàng)建可讀流
const readable = fs.createReadStream(filePath);
// 如果使用 readable.setEncoding() 方法為流指定了默認編碼
readable.setEncoding('utf8');

// 創(chuàng)建可寫流
const wirteable = fs.createWriteStream(copyFile);
// 編碼
wirteable.setDefaultEncoding('utf8');

readable.on('open', (fd) => {
  console.log('開始讀取文件')
})
// 每當流將數據塊的所有權移交給消費者時,則會觸發(fā) 'data' 事件
readable.on('data', (data) => {
  str += data;
  console.log('讀取到數據');

  // 寫入
  wirteable.write(data, 'utf8');
})

wirteable.on('open', () => {
  console.log('開始寫入數據')
})
// 如果對 stream.write(chunk) 的調用返回 false,則 'drain' 事件將在適合繼續(xù)將數據寫入流時觸發(fā)。
// 即生產數據的速度大于寫入速度,緩存區(qū)裝滿之后,會暫停生產著從底層讀取數據
// writeable緩存區(qū)釋放之后,會發(fā)送一個drain事件讓生產者繼續(xù)讀取
wirteable.on('drain', () => {
  console.log('繼續(xù)寫入')
})
// 在調用 stream.end() 方法之后,并且所有數據都已刷新到底層系統(tǒng),則觸發(fā) 'finish' 事件。
wirteable.on('finish', () => {
  console.log('數據寫入完畢')
})

readable.on('end', () => {
  // 數據讀取完畢通知可寫流
  wirteable.end()
})
// 當在可讀流上調用 stream.pipe() 方法將此可寫流添加到其目標集時,則觸發(fā) 'pipe' 事件。
// readable.pipe(destWriteable)
wirteable.on('pipe', () => {
  console.log('管道流創(chuàng)建')
})

wirteable.on('error', () => {
  console.log('數據寫入發(fā)生錯誤')
})

關于“Nodejs中stream流模塊怎么樣”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

網站名稱:Nodejs中stream流模塊怎么樣
網頁網址:http://bm7419.com/article14/gijcge.html

成都網站建設公司_創(chuàng)新互聯,為您提供品牌網站建設網站改版、虛擬主機、做網站動態(tài)網站、響應式網站

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

小程序開發(fā)