Wie schließe ich einen lesbaren Stream in 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.");
}
});
Das wäre besser als:
input.on('data', function(data) {
if (isEnded) { return; }
if (gotFirstLine) {
isEnded = true;
console.log("Closed.");
}
});
Dies würde den Lesevorgang jedoch nicht stoppen ...
fs
Moduls.close
existiert nicht inStream.Readable
.stream.destroy()
readable.push(null) && readable.destroy();
Antworten:
Rufen Sie auf
input.close()
. Es ist nicht in den Dokumenten, aberhttps://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620
macht den Job klar :) Es macht tatsächlich etwas Ähnliches wie dein
isEnded
.EDIT 2015-Apr-19 Basierend auf den Kommentaren unten und zur Klarstellung und Aktualisierung:
lib/fs.js
funktioniert es jedoch immer noch> 1,5 Jahre später.destroy()
dass ein Anruf vorzuziehen ist.fs
ReadStreams
's, nicht für ein GenerikumReadable
Was eine generische Lösung betrifft: Es sieht nicht so aus, als ob es eine gibt, zumindest nach meinem Verständnis der Dokumentation und nach einem kurzen Blick darauf
_stream_readable.js
.Mein Vorschlag wäre, Ihren lesbaren Stream in den angehaltenen Modus zu versetzen und zumindest eine weitere Verarbeitung in Ihrer Upstream-Datenquelle zu verhindern. Vergessen Sie nicht
unpipe()
, alledata
Ereignis-Listener zu entfernen, damit siepause()
tatsächlich pausieren, wie in den Dokumenten erwähntquelle
destroy
. Zumindest heißt das so, wenn Sie autoClose auf true setzen. Wenn man sich den Quellcode (heute) ansieht, sind die Unterschiede minimal (destroy
Aufrufeclose
), aber das könnte sich in Zukunft ändernclose()
lesbares Objekt. Gibt es eine Nie-Lösung? Mein Datenaustausch ist immer unvollständig ...Edit: Gute Nachrichten! Ab Node.js ist 8.0.0
readable.destroy
offiziell verfügbar: https://nodejs.org/api/stream.html#stream_readable_destroy_errorReadStream.destroy
Sie können die Funktion ReadStream.destroy jederzeit aufrufen .
Die öffentliche Funktion
ReadStream.destroy
ist nicht dokumentiert (Node.js v0.12.2), aber Sie können sich den Quellcode auf GitHub ansehen ( Commit vom 5. Oktober 2012 ).Die
destroy
Funktion markiert dieReadStream
Instanz intern als zerstört und ruft dieclose
Funktion zum Freigeben der Datei auf.Sie können das Ereignis close abhören, um genau zu wissen, wann die Datei geschlossen wird. Das Endereignis wird erst ausgelöst, wenn die Daten vollständig verbraucht sind.
Beachten Sie, dass die
destroy
(und dieclose
) Funktionen spezifisch für fs.ReadStream sind . Es gibt keinen Teil der generischen stream.readable "Schnittstelle".quelle
error
wenn er nie gelesen wird. Abgesehen davon ist das einzige andere Leck, über das ich mir Sorgen machen würde, Event-Handler - auch hier bin ich mir nicht 100% sicher, aber wir könnten in Ordnung sein, wenn das Evangelium von Isaacs 2010 besagt, dass Handler es sind beschnitten, wenn Emitter gc'd sind: groups.google.com/d/msg/nodejs/pXbJVo0NtaY/BxUmF_jp9LkJon('data')
wird der nur einmal ausgelöst, sodass keine vorhanden.close()
sind. Erinnern Sie einfach jemanden daran.Heute in Knoten 10
readableStream.destroy()
ist der offizielle Weg, um einen lesbaren Stream zu schließen
Siehe https://nodejs.org/api/stream.html#stream_readable_destroy_error
quelle
Das kannst du nicht. Es gibt keine dokumentierte Möglichkeit, einen generischen lesbaren Stream ab Knoten 5.3.0 zu schließen / herunterzufahren / abzubrechen / zu zerstören . Dies ist eine Einschränkung der Node-Stream-Architektur.
Wie andere Antworten hier erklärt haben, gibt es undokumentierte Hacks für bestimmte Implementierungen von Readable, die von Node bereitgestellt werden, wie z. B. fs.ReadStream . Dies sind jedoch keine generischen Lösungen für Lesbare.
Wenn mir hier jemand das Gegenteil beweisen kann, tun Sie es bitte. Ich möchte in der Lage sein, das zu tun, was ich sage, ist unmöglich, und würde mich freuen, korrigiert zu werden.
EDIT : Hier war meine Problemumgehung: Implementieren Sie
.destroy()
für meine Pipeline eine komplexe Reihe vonunpipe()
Aufrufen. Und nach all dieser Komplexität funktioniert es nicht in allen Fällen richtig .EDIT : Knoten V8.0.0 eine hinzugefügt
destroy()
api für Lesbare Ströme .quelle
stream.pipeline
, die behauptet, "Weiterleitungsfehler zu behandeln und ordnungsgemäß zu bereinigen und einen Rückruf bereitzustellen, wenn die Pipeline abgeschlossen ist". Hilft das?Bei der Version wird durch
4.*.*
Drücken eines Nullwerts in den Stream einEOF
Signal ausgelöst .Aus den NodeJS-Dokumenten
Dies funktionierte für mich, nachdem ich zahlreiche andere Optionen auf dieser Seite ausprobiert hatte.
quelle
Dieses Zerstörungsmodul soll sicherstellen, dass ein Stream zerstört wird und verschiedene APIs und Node.js-Fehler behandelt. Im Moment ist eine der besten Wahl.
NB. Ab Knoten 10 können Sie die
.destroy
Methode ohne weitere Abhängigkeiten verwenden.quelle
Sie können den Stream mit löschen und schließen
yourstream.resume()
, wodurch alles auf dem Stream abgelegt und schließlich geschlossen wird.Aus den offiziellen Dokumenten :
quelle
'data'
Ereignis-Listener, aber wir haben dafür gesorgt, dass ein Boolescher Wert überprüftif (!ignoring) { ... }
wird, damit beim Entleeren des Streams keine Daten verarbeitet werden.ignoring = true; readable.resume();
'end'
irgendwann wird. Das werden nicht alle Streams! (ZB ein Stream, der das Datum jede Sekunde für immer sendet.)Es ist eine alte Frage, aber auch ich habe nach der Antwort gesucht und die beste für meine Implementierung gefunden. Beide
end
undclose
Ereignisse werden ausgegeben, daher denke ich, dass dies die sauberste Lösung ist.Dies führt den Trick in Knoten 4.4 aus. * (Stabile Version zum Zeitpunkt des Schreibens):
Eine sehr detaillierte Erklärung finden Sie unter: http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm
quelle
Dieser Code hier macht den Trick gut:
writeStream.end () ist der Weg, um einen writeStream zu schließen ...
quelle
.end