¿Cómo cerrar una secuencia legible en 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.");
}
});
Esto sería mejor que:
input.on('data', function(data) {
if (isEnded) { return; }
if (gotFirstLine) {
isEnded = true;
console.log("Closed.");
}
});
Pero esto no detendría el proceso de lectura ...
fs
módulo.close
no existe enStream.Readable
.stream.destroy()
readable.push(null) && readable.destroy();
Respuestas:
Invocar
input.close()
. No está en los documentos, perohttps://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620
claramente hace el trabajo :) En realidad hace algo similar a tu
isEnded
.EDITAR 2015-Apr-19 Basado en los comentarios a continuación, y para aclarar y actualizar:
lib/fs.js
todavía funciona> 1,5 años después.destroy()
es preferible llamar .fs
ReadStreams
's, no en un genéricoReadable
En cuanto a una solución genérica: no parece que haya una, al menos según mi comprensión de la documentación y de un vistazo rápido a
_stream_readable.js
.Mi propuesta sería poner su flujo legible en modo pausado , al menos evitando un procesamiento adicional en su fuente de datos ascendente. No olvide
unpipe()
eliminar todos losdata
detectores de eventos para que sepause()
pause, como se menciona en los documentos.fuente
destroy
lugar. Al menos eso es lo que se llama si establece autoClose en verdadero. Al mirar el código fuente (hoy) las diferencias son mínimas (destroy
llamadasclose
) pero eso podría cambiar en el futuroclose()
un objeto legible, ¿nunca hay una solución? Mi intercambio de datos siempre está incompleto ...Editar: ¡ Buenas noticias! Comenzar con Node.js 8.0.0
readable.destroy
está oficialmente disponible: https://nodejs.org/api/stream.html#stream_readable_destroy_errorReadStream.destroy
Puede llamar a la función ReadStream.destroy en cualquier momento.
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'); });
La función pública
ReadStream.destroy
no está documentada (Node.js v0.12.2) pero puedes echar un vistazo al código fuente en GitHub ( confirmación del 5 de octubre de 2012 ).La
destroy
función marca internamente laReadStream
instancia como destruida y llama a laclose
función para liberar el archivo.Puede escuchar el evento de cierre para saber exactamente cuándo se cierra el archivo. El evento final no se activará a menos que los datos se consuman por completo.
Tenga en cuenta que las
destroy
(yclose
) funciones son específicas de fs.ReadStream . No forman parte de la "interfaz" legible de flujo genérico .fuente
error
si nunca se lee. Aparte de eso, la única otra filtración de la que me preocuparía son los controladores de eventos; una vez más, no estoy 100% seguro de esto, pero podríamos estar bien porque el 2010 el evangelio de Isaacs dice que los controladores son podado cuando los emisores son gc'd: groups.google.com/d/msg/nodejs/pXbJVo0NtaY/BxUmF_jp9LkJon('data')
solo se activará una vez, por lo que no habrá ninguno.close()
, solo recuerde a alguien más.Hoy, en el nodo 10
readableStream.destroy()
es la forma oficial de cerrar una transmisión legible
ver https://nodejs.org/api/stream.html#stream_readable_destroy_error
fuente
No puedes. No hay manera de cerrar / apagado / aborto / destruir un genérico sin documentados legible corriente como del Nodo 5.3.0. Ésta es una limitación de la arquitectura del flujo de nodo.
Como han explicado otras respuestas aquí, existen hacks no documentados para implementaciones específicas de Readable proporcionadas por Node, como fs.ReadStream . Sin embargo, estas no son soluciones genéricas para cualquier legible.
Si alguien puede demostrar que estoy equivocado, por favor hágalo. Me gustaría poder hacer lo que digo que es imposible, y estaría encantado de que me corrigieran.
EDITAR : Aquí estaba mi solución: implementar
.destroy()
para mi canalización a través de una serie compleja deunpipe()
llamadas. Y después de toda esa complejidad, no funciona correctamente en todos los casos .EDITAR : El nodo v8.0.0 agregó una
destroy()
api para transmisiones legibles .fuente
stream.pipeline
, que afirma manejar "errores de reenvío y limpieza adecuada y proporcionar una devolución de llamada cuando se completa la canalización". ¿Eso ayuda?En la versión, la
4.*.*
inserción de un valor nulo en la secuencia activará unaEOF
señal.De los documentos de nodejs
Esto funcionó para mí después de probar muchas otras opciones en esta página.
fuente
Este módulo de destrucción está destinado a garantizar que una secuencia se destruya, manejando diferentes API y errores de Node.js. Ahora mismo es una de las mejores opciones.
NÓTESE BIEN. Desde el Nodo 10 puede utilizar el
.destroy
método sin más dependencias.fuente
Puede limpiar y cerrar el flujo con
yourstream.resume()
, lo que volcará todo en el flujo y finalmente lo cerrará.De los documentos oficiales :
var readable = getReadableStreamSomehow(); readable.resume(); readable.on('end', () => { console.log('got to the end, but did not read anything'); });
fuente
'data'
detector de eventos, pero lo hicimos verificar un booleanoif (!ignoring) { ... }
para que no procese datos cuando estamos agotando la transmisión.ignoring = true; readable.resume();
'end'
en algún momento. ¡No todas las transmisiones harán eso! (Por ejemplo, una transmisión que envía la fecha cada segundo, para siempre.)Es una pregunta antigua, pero yo también estaba buscando la respuesta y encontré la mejor para mi implementación. Tanto
end
yclose
eventos consiguen emiten así que creo que esta es la solución más limpia.Esto hará el truco en el nodo 4.4. * (Versión estable en el momento de escribir este artículo):
var input = fs.createReadStream('lines.txt'); input.on('data', function(data) { if (gotFirstLine) { this.end(); // Simple isn't it? console.log("Closed."); } });
Para obtener una explicación muy detallada, consulte: http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm
fuente
Este código aquí hará el truco muy bien:
function closeReadStream(stream) { if (!stream) return; if (stream.close) stream.close(); else if (stream.destroy) stream.destroy(); }
writeStream.end () es la forma de ir para cerrar un writeStream ...
fuente
.end