首頁 > web前端 > js教程 > 主體

淺析Node.js的Stream模組中的Readable物件_node.js

WBOY
發布: 2016-05-16 15:48:16
原創
883 人瀏覽過

我一直都很不願意扯 nodejs 的流,因為從第一次看到它我就覺得它的設計實在是太噁心了。但沒辦法,Stream 規範尚未普及,而且確實有很多東西都依賴了nodejs 的流來實現的,所以我也只能捏著鼻子硬著頭皮來扯一扯這又臭又硬的nodejs 流物件了。
  nodejs 自帶了一個叫 stream 的模組,引入它便可以得到一組流物件建構器。現在我只說最簡單的 stream.Readable。
  其實實用過 nodejs 的幾乎都接觸過 Readable 的實例,只是平常沒太在意而已。一個很典型的例子,http 模組中我們處理每個請求時都會有 req 和 res 對象,req 其實就是一個 Readable 物件。我們可以在這個 req 上以流的形式讀到 HTTP 請求的實體部分。
  那麼問題來了,為什麼 http 模組要在這裡以流的方式設計呢?或從另一個維度來問這個問題就是「nodejs 如果取得 POST 請求的內容?」。懂得用搜尋引擎的同學肯定可以很容易地找到這麼一個答案:監聽 data 事件收集數據,在 end 事件中把收集到的數據合併起來。是的,這是解決這個問題的方法。但是為什麼它如此設計呢?像 PHP 直接就可以取到 POST 內容多好?其實這麼設計是有好處的,如果我們接收到的資料是非法的,我可以馬上察覺,然後回應並斷開連線。這樣可以避免一些不必要的傳輸成本。例如上傳圖片,也許使用者錯誤地選擇了一個很大的可執行文件,我們不需要等到這個文件完全上傳完畢,只要一個文件頭部的若干字節就能判斷一個文件是否是圖片了。這裡使用流的設計就可以先讀出前面的幾個位元組來使用。
  上述的 data 事件和 end 事件都是 Readable 的事件,這兩個事件分別表示收到資料和資料接收完畢。所以其實我們早已知道 Readable 的用法,只是很多人不知道它是 Readable 物件而已了。
  但是上面這兩個事件僅僅是對 Readable 的消費者而言的事件。內部是如何把一個資料推送到 Readable 物件裡面讓 Readable 觸發出這些事件的呢?那麼它就是 push 方法。下面是一個例子,它創建了一個 Readable 對象,這個對象會流出一個遞增的數字(這裡使用了 babel-node)

import stream from 'stream';

var r = new stream.Readable;

r.on('data', data => {
 console.log(data + '');
});

r.on('end', data => {
 console.log('end');
});

r._read = () => {
 // console.log('before read');
};

void function callee(i) {
 if(i < 10) {
  r.push(i + ''); // 只能传入字符串或 Buffre 对象
 } else {
  r.push(null); // 当输入一个 null 时表示流传输完成,触发 end 事件 
 }
 setTimeout(callee, 500, i + 1);
}(0);

登入後複製

  如果仔細看上面程式碼就會發現一個很神奇的地方,這個程式碼覆寫了 _read 方法,這是什麼鬼?其實我也覺得這是個坑,這個私有命名風格就不吐槽了,為何非要覆寫這個方法才算實現它?如果沒有覆寫這個方法,那麼在呼叫 push 時將會拋出異常:

 Error: not implemented
  at Readable._read (_stream_readable.js:464:22)
  at Readable.read (_stream_readable.js:341:10)
登入後複製

  以上這些便是 Readable 物件的基本用法。但還有更多坑會踩到,這篇文章只是一個最簡單的介紹,讓大家學會如何創造一個能輸出資料的 Readable 物件而已。至於一些 read 之類的基本方法,反正這些也是不科學的設計之一。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!