摘要:在可讀流事件里我們就必須調用方法。當一個對象就意味著我們想發出信號這個流沒有更多數據了自定義可寫流為了實現可寫流,我們需要使用流模塊中的構造函數。我們只需給構造函數傳遞一些選項并創建一個對象。
前言
什么是流呢?看字面意思,我們可能會想起生活中的水流,電流。
但是流不是水也不是電,它只是描述水和電的流動;所以說流是抽象的。
在node.js中流是一個抽象接口,它不關心文件內容,只關注是否從文件中讀到了數據,以及讀到數據之后的處理,接著看:
流是一組有序的,有起點和終點的字節數據傳輸手段
它不關心文件的整體內容,只關注是否從文件中讀到了數據;以及讀到數據之后的處理
流是一個抽象接口,被node中的很多對象所實現。比如HTTP服務器request和response對象都是流,TCP服務器中的socket也是流。
看看官網的介紹:
這里說了“所有的流都是EventEmitter的實例” 所以流繼承了EventEmitter類。再來看流的類型:
2.流的類型Reacable-可讀的流(例如fs.createReadStream())
Writrable-可寫的流(例如fs.createWriteStream())
Duplex-可讀寫的流(例如net.Socket)
Transform-在讀寫的過程中可以修改和變換數據的Duplex流(例如zlib.createDuplex())
3.流的數據模式流中的數據有兩種模式,二進制模式和對象模式.
二進制模式, 每個分塊都是buffer或者string對象.
對象模式, 流內部處理的是一系列普通對象.
注意:4.可讀流(createReadStream) 4.1 創建可讀流
所有使用 Node.js API 創建的流對象都只能操作 strings 和 Buffer對象。但是,通過一些第三方流的實現,你依然能夠處理其它類型的 JavaScript 值 (除了 null,它在流處理中有特殊意義)。 這些流被認為是工作在 “對象模式”(object mode)。 在創建流的實例時,可以通過 objectMode 選項使流的實例切換到對象模式。試圖將已經存在的流切換到對象模式是不安全的。
說了那么多,現在開始寫流:
這里說說流程:
首先可讀流會打開文件,觸發open事件
接著開始讀取,瘋狂的觸發data事件
然后讀完了,觸發end事件
最后因為設置了autoClose為true,自動關閉文件觸發close事件
可以看到,data事件不斷的被觸發,當我們想讀一下停一下時怎么辦呢?
這里就需要聊聊可讀流的兩種模式:
可讀流事實上工作在下面兩種模式之一:flowing 和 paused
在 flowing 模式下, 可讀流自動從系統底層讀取數據,并通過 EventEmitter 接口的事件盡快將數據提供給應用。
在 paused 模式下,必須顯式調用 stream.read() 方法來從流中讀取數據片段。
初始工作模式為 paused 的 Readable 流,可以通過下面三種途徑切換到 flowing 模式:
1. 監聽 "data" 事件 2. 調用 stream.resume() 方法
3.調用 stream.pipe() 方法將數據發送到 Writable
注意:
如果 Readable 切換到 flowing 模式,且沒有消費者處理流中的數據,這些數據將會丟失。 比如, 調用了 readable.resume() 方法卻沒有監聽 "data" 事件,或是取消了 "data" 事件監聽,就有可能出現這種情況
在 paused 模式下,必須顯式調用 stream.read() 方法來從流中讀取數據片段。
在可讀流"readable"事件里我們就必須調用stream.read()方法。
這里需要明白三點:
先創建一個1.txt
1.當我只要創建一個流 就會先把緩存區 填滿,等待著你自己消費
2.當你消費小于 最高水位線時 會自動添加highWaterMark這么多數據
3.如果當前緩存區被清空后會再次觸發readable事件
用Readable創建對象readable后,便得到了一個可讀流。
如果實現_read方法,就將流連接到一個底層數據源。
流通過調用_read向底層請求數據,底層再調用流的push方法將需要的數據傳遞過來。
當readable連接了數據源后,下游便可以調用readable.read(n)向流請求數據,同時監聽readable的data事件來接收取到的數據。
5.可寫流(createWriteStream) 5.1 創建可寫流 5.1.1 write方法 5.1.2 end方法表明接下來沒有數據要被寫入 Writable 通過傳入可選的 chunk 和 encoding 參數,可以在關閉流之前再寫入一段數據 如果傳入了可選的 callback 函數,它將作為 "finish" 事件的回調函數5.1.3 drain方法
drain事件的觸發條件,必須滿足兩個條件:
1.當前緩存區滿了,不能再寫了
2.緩存區滿了后被清空了,才會觸發drain事件
我們在開發中可能會遇到,要把可讀流讀出的數據需要放到可寫流中去寫入到文件里面,這時就可以用pipe方法
6.1 pipe的原理pipe方法的原理很簡單,就是讀一點,寫一點,上代碼
let fs = require("fs"); let ws = fs.createWriteStream("./2.txt"); let rs = fs.createReadStream("./1.txt"); rs.on("data", data => { var flag = ws.write(data); if(!flag) rs.pause(); }); ws.on("drain", () => { rs.resume(); }); rs.on("end", () => { ws.end(); });6.2 pipe的用法
let from = fs.createReadStream("./1.txt"); let to = fs.createWriteStream("./2.txt"); from.pipe(to);6.3 unpipe方法
readable.unpipe()方法將之前通過stream.pipe()方法綁定的流分離
let fs = require("fs"); let from = fs.createReadStream("./1.txt"); let to = fs.createWriteStream("./2.txt"); from.pipe(to); setTimeout(() => { console.log("關閉向2.txt的寫入"); from.unpipe(writable); console.log("手動關閉可寫流"); to.end(); }, 1000);7.自定義流
我們可以引入stream模塊,想實現什么流 就繼承這個流。
7.1 自定義可讀流我們可以直接把供使用的數據push出去。
當push一個null對象就意味著我們想發出信號——這個流沒有更多數據了
7.2 自定義可寫流為了實現可寫流,我們需要使用流模塊中的Writable構造函數。 我們只需給Writable構造函數傳遞一些選項并創建一個對象。唯一需要的選項是write函數,該函數揭露數據塊要往哪里寫。
有了雙工流,我們可以在同一個對象上同時實現可讀和可寫,就好像同時繼承這兩個接口。 重要的是雙工流的可讀性和可寫性操作完全獨立于彼此。
net中的Socket就是一個duplex雙工流
說到這里,我想大家應該大致了解了node.js里面的流。
之前說過在node里流還是很重要的,http里的request和response都是流。
在下一篇文章我會寫一個readStream和writeStream的簡單實現。
本人水平有限,有錯誤的地方希望指出。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93907.html
摘要:事件的觸發頻次同樣是由實現者決定,譬如在進行文件讀取時,可能每行都會觸發一次而在請求處理時,可能數的數據才會觸發一次。如果有參數傳入,它會讓可讀流停止流向某個特定的目的地,否則,它會移除所有目的地。 showImg(https://segmentfault.com/img/remote/1460000016328758?w=1967&h=821); 本文節選自 Node.js Chea...
摘要:回調函數中檢測該次寫入是否被緩沖,若是,觸發事件。若目標可寫流表示該寫入操作需要進行緩沖,則立刻將源可讀流切換至暫停模式。監聽源可讀流的事件,相應地結束目標可寫流。 在Node.js中,流(Stream)是其眾多原生對象的基類,它對處理潛在的大文件提供了支持,也抽象了一些場景下的數據處理和傳遞。在它對外暴露的接口中,最為神奇的,莫過于導流(pipe)方法了。鑒于近期自己正在閱讀Node...
摘要:中的流十分強大,它對處理潛在的大文件提供了支持,也抽象了一些場景下的數據處理和傳遞。本文將會提供兩個在編寫基于流的工具時,私以為有些用的兩個。 Node.js中的流十分強大,它對處理潛在的大文件提供了支持,也抽象了一些場景下的數據處理和傳遞。正因為它如此好用,所以在實戰中我們常常基于它來編寫一些工具 函數/庫 ,但往往又由于自己對流的某些特性的疏忽,導致寫出的 函數/庫 在一些情況會達...
摘要:中各種用于讀取數據的對象對象描述用于讀取文件代表客戶端請求或服務器端響應代表一個端口對象用于創建子進程的標準輸出流。如果子進程和父進程共享輸入輸出流,則子進程的標準輸出流被廢棄用于創建子進程的標準錯誤輸出流。 9. stream流 fs模塊中集中文件讀寫方法的區別 用途 使用異步方式 使用同步方式 將文件完整讀入緩存區 readFile readFileSync 將文件部...
摘要:方法也可以接收一個參數表示數據請求著請求的數據大小,但是可讀流可以根據需要忽略這個參數。讀取數據大部分情況下我們只要簡單的使用方法將可讀流的數據重定向到另外形式的流,但是在某些情況下也許直接從可讀流中讀取數據更有用。 介紹本文介紹了使用 node.js streams 開發程序的基本方法。 We should have some ways of connecting programs ...
閱讀 1618·2021-11-22 13:53
閱讀 2848·2021-11-15 18:10
閱讀 2755·2021-09-23 11:21
閱讀 2491·2019-08-30 15:55
閱讀 475·2019-08-30 13:02
閱讀 752·2019-08-29 17:22
閱讀 1659·2019-08-29 13:56
閱讀 3455·2019-08-29 11:31