スキップしてメイン コンテンツに移動

Node.js でメモリ上のデータから stream を作る

fs.createReadStream() 等でストリームを作るのではなく、メモリ上のデータでストリームを開始する方法です。

但し、node.js のストリームの触り始めの人が書いているので話半分で。

サンプルコードの概要

  1. サンプルは Web サーバのレスポンスを想定しています。
  2. 返信文書(データ)の用意までに1000ミリ秒を要し、このデータはメモリ上に用意されます。
  3. しかし、他の Web ページの配信にも使用しているファイルストリームのトランスフォーマー(common/transformer.js) を共有したいので、メモリ上のデータをストリームに変換する、というシナリオです。

MemoryReadableStream クラス

まずは MemoryReadableStream クラスを定義します。

データの準備に時間がかかるのでコンストラクタの中で pause() しています。

データが用意出来たら、再開 resume() する時に、引数に全てのデータを渡します。このデータに続いてストリームの終わりを示す null が送られます。

const stream = require('stream');

class MemoryReadableStream extends stream.Readable{
  constructor(){
    super();
    this._data = '';
    this.pause();
  }
  _read(n){
    this.push(this._data);
  }
  resume(data){
    if(this.paused && data && this._data !== null){
      this.push(data);
      this._data = null;
    };
    super.resume();
  }
};

1秒後にウェブページを返す Web サーバの例

続いて MemoryReadableStream インスタンスを作って、transformer を pipe() します。

1秒の時間を要する処理の後に、出来あがったデータを引数に resume(data) を呼びます。

このデータは transformer での処理を経て、完全な HTML 文書となってウェブブラウザに送信されます。

const transformer = require('common/transformer.js');

require('http').createServer(
  (request, response) => {
    const stream = new MemoryReadableStream();
    
    stream.pipe(transformer).pipe(response);

    setTimeout(
      function(){
        if (!stream.ended) stream.resume('...data...');
      }, 1000
    ); 
  }
).listen(8080);