node.js - tutorial - El evento "legible" ocurre dos veces
stream nodejs (2)
Después de que Node.js cargue el archivo (completo o solo una parte, depende del tamaño del archivo) en el búfer (usando el método push ()) emitirá readable event
para indicar que algunos datos se han leído en el buffer y está listo para usar. Luego, después de llamar a read(10)
, liberará el búfer y luego Node.js volverá a llenar el búfer automáticamente y emitirá de nuevo el readable event
para indicar que todavía hay datos para leer del búfer. Si llamara a read(700)
, no se emitiría ningún otro readable event
nuevamente.
Modo de flujo y no flujo
A diferencia de cuando se escucha un data event
la transmisión permanecerá en el llamado modo no fluido. Eso significa que el desarrollador será responsable de liberar la transmisión (leyendo de la transmisión). Por otro lado, al escuchar un data event
la transmisión entrará automáticamente en el llamado modo de flujo, lo que significa que la secuencia en sí misma será responsable de liberarse, es decir, la secuencia se llenará y vaciará hasta el sistema subyacente (en este caso, zero.txt
se leerá por completo). Tenga en cuenta que el búfer se llenará de datos automáticamente en cualquier modo.
Modo de flujo
Un ejemplo del modo no fluido, donde tenemos que vaciar el búfer manualmente (utilizando el método read()
):
var fs = require(''fs''),
util = require(''util'');
// I have increased the file size to 19 MB (about 19 mln characters);
// Cause of the buffer capicity.
var file = fs.createReadStream(''./zeros.txt'');
var dataSize = 0;
// Readable will be called when the buffer has been filled with data.
// Initially Node.js will fill the buffer with data automatically,
// so this event will be called automatically aswell of course.
// Once the buffer will be free again after the first fill, Node.js
// will fill the buffer automatically again. Node.js just watches this stream
// and makes sure to fill it, when there is still some unread data in the zero.txt file.
file.on(''readable'', function() {
var i = 0; // we will count how many times did while loop, for fun
// If the buffer will be empty Node will write data to the buffer
// automatically, we don''t have to care about that. However
// you can specify the buffer capicty manually if you want.
console.log(''loading more data from the underlying system'');
// This will make the stream read 1000 bytes
// it will also return a value NULL if there is not enough
// data to read from the buffer (meaning buffer has been fully read
// or there is still some data but you are trying to read 1000 bytes
// and there is less than 1000 bytes left)
while(file.read(1000) !== null) {
i++;
}
// At this moment while loop has read everything from the buffer.
// The buffer is now empty. After this comment console.log will execute
// Node.js will fill the buffer again with new data automatically.
// And then the ''readable'' event will fire again.
console.log("had to loop: " + i + " times before the buffer was empty");
})
Últimos resultados de la consola:
loading more data from the underlying system
had to loop: 66 times before the buffer was empty
loading more data from the underlying system
had to loop: 65 times before the buffer was empty
loading more data from the underlying system
had to loop: 66 times before the buffer was empty
loading more data from the underlying system
had to loop: 46 times before the buffer was empty
loading more data from the underlying system
had to loop: 1 times before the buffer was empty
Modo no fluido
Ese era el modo no fluido, ya que teníamos que liberar el búfer manualmente. Ahora procederemos al modo de flujo. Al establecer un data event listener
en una Readable Stream
legible, la transmisión cambia al flowing mode
desde el flowing mode
inicial que non-flowing mode
. Eso significa que el buffer se vaciará automáticamente. Node.js pasará los datos como un argumento en el data event listener
, y una vez que esa función se ejecute, el búfer se vaciará nuevamente y si todavía hay algunos datos en el búfer fuente subyacente se llenarán automáticamente con nuevos datos, y luego los datos evento será emitido nuevamente. NOTA: si está escuchando el evento de data
y el readable event
ambos se dispararán pero el data event listener
primero vaciará el búfer y ENTONCES se disparará el readable event
para que su read()
siempre devuelva NULL
.
var fs = require(''fs''),
util = require(''util'');
var file = fs.createReadStream(''./zeros.txt'');
var dataSize = 0;
file.on(''data'', function() {
// Once this listener will stop executing new data will be read
// into the buffer and then the ''data'' event will be emitted
// again.
console.log(''data has been loaded and emptied!'')
})
file.on(''readable'', function () {
// Notice we want to try to read 1 byte from the buffer
// but in the console we see that the read() method
// resulted in NULL, which means that the buffer is empty.
// That''s of course because we enterd the flowing mode
// by setting up the ''data'' event. (In flowing mode)
// after the execution of the ''data'' event all data
// from the buffer will be read, but the execution
// of listeners will continue. After all the event listeners
// attached to this stream will execute, Node.js will fill
// the buffer automatically again.
console.log(''readable '' + file.read(1))
});
Últimos resultados de la consola:
data has been loaded and emptied!
readable null
data has been loaded and emptied!
readable null
data has been loaded and emptied!
readable null
data has been loaded and emptied!
readable null
data has been loaded and emptied!
readable null
var fs = require(''fs'');
var file = fs.createReadStream(''./zeros.txt'');
var dataSize = 0;
file.on(''readable'', function () {
var data = file.read(10);
console.log(''readable size = '', data.length);
console.log(data.toString());
});
El archivo "zeros.txt" contiene 700 caracteres "0"
Según tengo entendido, después de llamar a read (10), la transmisión debe detenerse y esperar una nueva llamada de lectura (). Sin embargo, el resultado de llamar:
readable size = 10
0000000000
readable size = 10
0000000000
Mi respuesta se basa en la versión de 0.12.4.
1: Cada función de read(n)
que se extiende desde Stream.Readable
desencadenará la función _read(n)
interna cuando la longitud del búfer interno actual sea 0 o menor que el valor de la propiedad highWaterMark
.
2: El evento readable
solo se activará cuando la longitud del búfer interno actual sea 0 o los datos leídos del búfer interno sean nulos o se haya producido un indicador nulo .
Tomemos su código como ejemplo para ver qué sucedió.
file.on(''readable'', function () {
Un registro de manejador de eventos readable
activará la función de read(0)
para cargar los datos del archivo al búfer interno. Si no sobrescribe el valor de highWaterMark
, cargará 64 * 1024 = 65535 fragmentos como máximo. En su código, cargó todos los datos del archivo "zeros.txt". Después de eso, activará el evento readable
porque la longitud del búfer interno es 0 antes de que se invoque la función read(0)
.
var data = file.read(10);
En el controlador, invocó de nuevo la función de read(10)
. Esto también activaría el proceso de carga de un archivo a un búfer. Sin embargo, no se cargarán datos en este momento. Por lo tanto, se presionaría null
para indicar que el proceso de lectura se completó. El segundo evento readable
se había activado. Esta es la razón por la que debería ver y solo ver dos eventos readable
.
Si lee un archivo cuyo tamaño es mayor que 65535 bytes (casi 66 KB), solo debería ver un evento readable
activado.
No debe escribir controladores de eventos readable
así, debe consultar lo siguiente:
var chunk;
while( null !== ( chunk = fs.read() ) ) {
//handle the chunk
}
Si desea manejar el trozo en su camino para hacer algunas cosas especiales, tenga cuidado con las reglas; de lo contrario, el programa permanecerá en estado de "pausa", no se leerán más datos y no se recuperarán más datos.
Por favor, consulte fs.ReadStream y stream.Readable .