詳解Node Stream

前言

以前基於流處理構建工具gulp介紹,如今對stream模塊進行簡要分析,以便更好的使用構建工具,以及進行插件開發。javascript

Stream

Stream模塊有四個類,Readable, Writable, Duplex, TransformTransform能夠看作自成體系的子類。從使用角度來講,模塊定義的類都爲基類,是不具有直接使用條件的,須要程序實現相關接口方可以使用。java

Stream.Readable

此類須要實現_read接口,用通俗的話來說,可讀流至關於發貨倉庫,倉庫中的貨物儲備交由_read處理,具體發貨模塊內部自行處理。可讀流對象有flowing modenon-flowing mode兩種模式,前者自動處理髮貨,後者須要手動控制發貨。git

javascript// inherit stream.Readable
function Love() {
  stream.Readable.call(this);
  this._max = 5;
  this._index = 0;
}
util.inherits(Love, stream.Readable);

Love.prototype._read = function() {
  var i = this._index++;
  if (i > this._max) {
    this.push('beautiful');
    this.push(null);
  }
  else {
    var str = '' + i;
    var buf = new Buffer(str, 'utf8');
    this.push(buf);
  }
};

在初始化時,會自動調用_read方法,利用ctx.push方法寫入內容到內部存儲buffer(進貨)。代碼很簡單,傳輸的內容爲0-5,以及單詞beautiful。如今倉庫中已經有貨物,而後處理髮貨流程。github

flowing mode下,監聽data事件便可,non-flowing mode下,使用readable.read方法獲取內容,兩種方式實際效果等同。此處readable事件觸發比較不解,暫時沒法深刻。gulp

javascript// flowing mode
title.on('data', function(data) {
  writer.write(data);
});
// non-flowing mode
title.on('readable', function() {
  var chunk;
  while (null !== (chunk = title.read())) {
    writer.write(chunk);
  }
});

至此,能夠簡單理解可讀流就是進貨出貨的方式,定義接口實現進貨,數據讀取實現出貨。工具

stream.Writable

此類須要實現_write接口,用通俗的話來說,可寫流就是快遞簽收的過程。賣家不斷髮貨,買家不斷收貨,簽收的流程就是由_write接口定義。this

javascript// inherit stream.Writable
function Story() {
  stream.Writable.call(this);
  this._storage = new Buffer('');
}
util.inherits(Story, stream.Writable);

Story.prototype._write = function(chunk, encoding, callback) {
  this._storage = Buffer.concat([this._storage, chunk]);
  callback();
};

此處定義方式很簡單,收到數據後,將數據保存在this._storage私有變量中,這樣就定義好可寫流。下面來看如何綜合使用兩個類。prototype

javascriptvar reader = new Love();
var writer = new Story();

reader.on('readable', function() {
  var chunk;
  while (null !== (chunk = title.read())) {
    writer.write(chunk);
  }
});

reader.on('end', function() {
  writer.end();
});

writer.on('finish', function() {
  fs.writeFileSync('./output.txt', this._storage);
});

此處使用,將可讀流傳下來的數據所有寫入output.txt文件之中,很是簡單的示例。插件

stream.Duplex

可讀可寫流,兼而有之二者特性,不清楚是否能夠同時兼任二者,本人暫時未找處處理方案。code

stream.Transform

可以同時兼任可讀流與可寫流,gulp插件總結來講,就是自定義的stream.Transform流。須要實現接口_transform_flush,二者均可以_read的特色,能夠向後傳遞數據。

javascriptfunction Knight() {
  stream.Transform.call(this);
}
util.inherits(Knight, stream.Transform);

Knight.prototype._transform = function(chunk, encoding, callback) {
  this.push(chunk);
  callback();
};

Knight.prototype._flush = function(callback) {
  this.push('dark knight');
  callback();
};

示例很是簡單,在內容後面再加上dark knight字符串,再也不贅述。

總結

對全部流來講,一般使用pipe方法更爲簡便直接,因此應避免使用其餘方式。完整代碼地址:http://snowykiss.qiniudn.com/stream.js

聯繫方式

QQ: 491229492
https://github.com/bornkiller

相關文章
相關標籤/搜索