Jak zamknąć czytelny strumień w 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.");
}
});
To byłoby lepsze niż:
input.on('data', function(data) {
if (isEnded) { return; }
if (gotFirstLine) {
isEnded = true;
console.log("Closed.");
}
});
Ale to nie zatrzymałoby procesu czytania ...
fs
modułu.close
nie istnieje wStream.Readable
.stream.destroy()
readable.push(null) && readable.destroy();
Odpowiedzi:
Wywołaj
input.close()
. Nie ma tego w dokumentach, alehttps://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620
najwyraźniej spełnia swoje zadanie :) W rzeczywistości robi coś podobnego do twojego
isEnded
.EDYCJA 2015-kwiecień-19 Na podstawie poniższych komentarzy oraz wyjaśnienia i aktualizacji:
lib/fs.js
, nadal działa> 1,5 roku później.destroy()
preferowanego dzwonienia .fs
ReadStreams
's, a nie dla generycznychReadable
Jeśli chodzi o ogólne rozwiązanie: nie wydaje się, żeby takie istniało, przynajmniej z mojego zrozumienia dokumentacji i szybkiego spojrzenia
_stream_readable.js
.Moja propozycja polegałaby na przestawieniu czytelnego strumienia w tryb wstrzymania , co najmniej zapobiegając dalszemu przetwarzaniu w źródle danych. Nie zapomnij
unpipe()
i usuń wszystkiedata
detektory zdarzeń, abypause()
faktycznie zostały wstrzymane, jak wspomniano w dokumentacjiźródło
destroy
zamiast tego zadzwonić . Przynajmniej tak się nazywa, jeśli ustawisz autoClose na true. Patrząc na kod źródłowy (dzisiaj) różnice są minimalne (destroy
wywołaniaclose
), ale to może się zmienić w przyszłościclose()
na obiekt czytelny, czy nigdy nie ma rozwiązania? Moja wymiana danych jest zawsze niepełna ...Edycja: Dobra wiadomość! Począwszy od Node.js 8.0.0
readable.destroy
jest oficjalnie dostępny: https://nodejs.org/api/stream.html#stream_readable_destroy_errorReadStream.destroy
W dowolnym momencie możesz wywołać funkcję 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'); });
Funkcja publiczna
ReadStream.destroy
nie jest udokumentowana (Node.js v0.12.2), ale możesz rzucić okiem na kod źródłowy na GitHub ( zatwierdzenie 5 października 2012 ).destroy
Funkcja wewnętrznie zaznaczyćReadStream
instancję jako zniszczone i wywołujeclose
funkcję, aby zwolnić plik.Możesz słuchać zdarzenia close, aby dokładnie wiedzieć, kiedy plik zostanie zamknięty. Wydarzenie koniec nie zadziała, chyba że dane są całkowicie zużyte.
Zauważ, że funkcje
destroy
(iclose
) są specyficzne dla fs.ReadStream . Nie ma części ogólnego "interfejsu" stream.readable .źródło
error
zostanie uruchomiony, jeśli nigdy nie zostanie odczytany. Poza tym jedynym innym przeciekiem, o który się martwię, są programy obsługi zdarzeń - po raz kolejny nie jestem tego w 100% pewien, ale możemy być w porządku przed 2010 rokiem, według ewangelii Izaaka przycinane, gdy emitery są gc'd: groups.google.com/d/msg/nodejs/pXbJVo0NtaY/BxUmF_jp9LkJon('data')
wyzwolą się tylko raz, więc nie będzie żadnych.close()
, po prostu przypomnij komuś innemu.Dziś w węźle 10
readableStream.destroy()
to oficjalny sposób na zamknięcie czytelnego strumienia
zobacz https://nodejs.org/api/stream.html#stream_readable_destroy_error
źródło
Nie możesz. Nie ma udokumentowanego sposobu na zamknięcie / zamknięcie / przerwanie / zniszczenie ogólnego strumienia do odczytu od Węzła 5.3.0. Jest to ograniczenie architektury strumienia Node.
Jak wyjaśniły inne odpowiedzi tutaj, istnieją nieudokumentowane hacki dla określonych implementacji Readable dostarczanych przez Node, takich jak fs.ReadStream . Nie są to jednak ogólne rozwiązania dla żadnego Readable.
Jeśli ktoś może mi tutaj udowodnić, że się mylę, zrób to. Chciałbym móc robić to, co mówię, jest niemożliwe i byłbym zachwycony, gdybym został skorygowany.
EDYCJA : Oto moje obejście: zaimplementuj
.destroy()
dla mojego potoku przez złożoną serięunpipe()
wywołań. Po całej tej złożoności nie we wszystkich przypadkach działa poprawnie .EDYCJA : Węzeł v8.0.0 dodał
destroy()
interfejs API dla strumieni czytelnych .źródło
stream.pipeline
, który twierdzi, że radzi sobie z „błędami przekazywania i prawidłowym czyszczeniem oraz zapewnia wywołanie zwrotne po zakończeniu potoku”. To pomaga?W wersji
4.*.*
wstawienie wartości null do strumienia wyzwoliEOF
sygnał.Z dokumentacji nodejs
To zadziałało dla mnie po wypróbowaniu wielu innych opcji na tej stronie.
źródło
Ten moduł niszczenia ma na celu zapewnienie zniszczenia strumienia, obsługując różne interfejsy API i błędy Node.js. W tej chwili jest to jeden z najlepszych wyborów.
NB. W węźle 10 możesz używać tej
.destroy
metody bez dalszych zależności.źródło
Możesz wyczyścić i zamknąć strumień
yourstream.resume()
, co spowoduje zrzucenie wszystkiego w strumieniu i ostatecznie zamknięcie go.Z oficjalnych dokumentów :
var readable = getReadableStreamSomehow(); readable.resume(); readable.on('end', () => { console.log('got to the end, but did not read anything'); });
źródło
'data'
detektor zdarzeń, ale sprawiliśmy, że sprawdzał wartość logiczną,if (!ignoring) { ... }
aby nie przetwarzał danych podczas opróżniania strumienia.ignoring = true; readable.resume();
'end'
w pewnym momencie. Nie wszystkie strumienie to zrobią! (Np. Strumień, który wysyła datę co sekundę, na zawsze.)To stare pytanie, ale ja również szukałem odpowiedzi i znalazłem najlepsze dla mojej realizacji. Emitowane są zarówno zdarzenia, jak
end
iclose
zdarzenia, więc myślę, że jest to najczystsze rozwiązanie.To załatwi sprawę w węźle 4.4. * (Stabilna wersja w momencie pisania):
var input = fs.createReadStream('lines.txt'); input.on('data', function(data) { if (gotFirstLine) { this.end(); // Simple isn't it? console.log("Closed."); } });
Bardzo szczegółowe wyjaśnienie można znaleźć pod adresem : http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm
źródło
Ten kod tutaj załatwi sprawę:
function closeReadStream(stream) { if (!stream) return; if (stream.close) stream.close(); else if (stream.destroy) stream.destroy(); }
writeStream.end () to najlepszy sposób na zamknięcie metody writeStream ...
źródło
.end