web-dev-qa-db-ja.com

読み取り可能なストリームを閉じる方法(終了前)

Node.jsで 読み取り可能なストリーム を閉じる方法は?

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   // after closing the stream, this will not
   // be called again

   if (gotFirstLine) {
      // close this stream and continue the
      // instructions from this if
      console.log("Closed.");
   }
});

これは次の場合よりも優れています。

input.on('data', function(data) {
   if (isEnded) { return; }

   if (gotFirstLine) {
      isEnded = true;
      console.log("Closed.");
   }
});

しかし、これは読み取りプロセスを停止しません...

76
Ionică Bizău

input.close()を呼び出します。ドキュメントにはありませんが、

https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L162

明らかに仕事をします:)実際にあなたのisEndedに似た何かをします。

EDIT 2015-Apr-19以下のコメントに基づき、明確化および更新するため:

  • この提案はハッキングであり、文書化されていません。
  • 現在のlib/fs.jsを見ると、1.5年以上後でも動作します。
  • destroy()の呼び出しが望ましいという以下のコメントに同意します。
  • 以下に正しく記載されているように、これはfsReadStreamsに対して機能しますが、汎用のReadableでは機能しません

一般的な解決策に関しては、少なくともドキュメントの理解と_stream_readable.jsのクイックルックからは、それが存在するようには見えません。

私の提案では、読み取り可能なストリームをpausedモードにし、少なくともアップストリームデータソースでのさらなる処理を防ぎます。 ドキュメント で説明されているように、unpipe()を忘れずにdataイベントリスナーをすべて削除して、pause()が実際に一時停止するようにしてください。

29
Nitzan Shaked

編集:良いニュース! Node.js 8.0.0以降、readable.destroyが正式に利用可能になりました: https://nodejs.org/api/stream.html#stream_readable_destroy_error

ReadStream.destroy

ReadStream.destroy 関数はいつでも呼び出すことができます。

var fs = require('fs');

var readStream = fs.createReadStream('lines.txt');
readStream
    .on('data', function (chunk) {
        console.log(chunk);
        readStream.destroy();
    })
    .on('end', function () {
        // This may not been called since we are destroying the stream
        // the first time 'data' event is received
        console.log('All the data in the file has been read');
    })
    .on('close', function (err) {
        console.log('Stream has been destroyed and file has been closed');
    });

パブリック関数ReadStream.destroyはドキュメント化されていません(Node.js v0.12.2)が、 GitHubのソースコードOct 5、2012 commit =)。

destroy関数は内部でReadStreamインスタンスを破棄済みとしてマークし、close関数を呼び出してファイルを解放します。

close event をリッスンして、ファイルがいつ閉じられたかを正確に知ることができます。 end event は、データが完全に消費されない限り起動しません。


destroy(およびclose)関数は fs.ReadStream に固有であることに注意してください。ジェネリック stream.readable "interface"の一部はありません。

54
Yves M.

今日、Node 10

readableStream.destroy()

読み取り可能なストリームを閉じる公式の方法です

https://nodejs.org/api/stream.html#stream_readable_destroy_error を参照してください

17
Jo-Go

できません。 Node 5.3.0の時点で、一般的な Readable ストリームを閉じる、シャットダウン、中止、破棄する文書化された方法はありません。これは、Nodeストリームアーキテクチャの制限です。

ここでの他の回答で説明したように、Nodeが提供するReadableの特定の実装( fs.ReadStream など)について文書化されていないハックがあります。ただし、これらはReadableの一般的なソリューションではありません。

ここで誰かが間違っていることを証明できる場合は、してください。私は不可能だと言っていることをできるようになりたいし、修正されることを喜んでいるだろう。

編集:ここに私の回避策がありました: 実装.destroy()複雑な一連のunpipe()呼び出し。 そして、すべてのその複雑さの後に、それは- すべての場合に正しく動作しません

編集:Node v8.0.0が追加されました destroy()読み取り可能なストリームのAPI

11
thejoshwolfe

バージョン4.*.*では、null値をストリームにプッシュすると、EOFシグナルがトリガーされます。

nodejs docs から

Null以外の値が渡された場合、Push()メソッドは、後続のストリームプロセッサが消費するデータのチャンクをキューに追加します。 nullが渡された場合、ストリームの終わり(EOF)を通知し、その後データを書き込むことはできません。

このページで他の多くのオプションを試した後、これはうまくいきました。

10
Jacob Lowe

この destroy モジュールは、ストリームが確実に破棄され、さまざまなAPIとNode.jsのバグを処理することを目的としています。今は最良の選択の一つです。

NB。Node 10から、.destroyメソッドをさらに依存関係なしで使用できます。

5
Rocco Musolino

それは古い質問ですが、私も答えを探していて、私の実装に最適なものを見つけました。 endイベントとcloseイベントの両方が発行されるため、これが最もクリーンなソリューションだと思います。

これにより、ノード4.4。*(執筆時点での安定バージョン)でトリックが実行されます。

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   if (gotFirstLine) {
      this.end(); // Simple isn't it?
      console.log("Closed.");
   }
});

非常に詳細な説明については、以下を参照してください: http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm

3
Vexter

yourstream.resume()を使用してストリームをクリアして閉じることができます。これにより、ストリーム上のすべてがダンプされ、最終的には閉じられます。

公式ドキュメント から:

readable.resume():

戻り値:これ

このメソッドにより、読み取り可能なストリームが「データ」イベントの発行を再開します。

このメソッドは、ストリームをフローモードに切り替えます。ストリームからデータを消費したくないが、その「終了」イベントに到達したい場合は、stream.resume()を呼び出してデータのフローを開くことができます。

var readable = getReadableStreamSomehow();
readable.resume();
readable.on('end', () => {
  console.log('got to the end, but did not read anything');
});
3
Sayem

ここのこのコードはうまくトリックをします:

function closeReadStream(stream) {
    if (!stream) return;
    if (stream.close) stream.close();
    else if (stream.destroy) stream.destroy();
}

writeStream.end()は、writeStreamを閉じる方法です...

2
g00dnatur3