‫-: Muy bien, ahora vamos a trabajar con streams.
‫Y nuevamente, comenzando por crear un nuevo archivo.
‫Está bien. Ahora digamos que por
‫alguna razón en nuestra aplicación, necesitamos leer un archivo de texto grande
‫del sistema de archivos y luego enviarlo al cliente.
‫Entonces, ¿cómo haríamos eso?
‫Bueno, hay varias formas y vamos a explorar
‫algunas de ellas, comenzando con la
‫más básica y avanzando hasta la mejor manera de hacerlo.
‫Bien, entonces lo primero es requerir el paquete del
‫sistema de archivos como antes, y también el módulo HTTP.
‫Permítanme mostrarles un buen truco, así que
‫creemos un servidor como este.
‫Entonces, requiera el paquete HTTP, y luego desde aquí podemos
‫llamar de inmediato a createServer. Así que así.
‫Bien, entonces el resultado de requerir HTTP, es el
‫objeto HTTP y allí podemos usar createServer.
‫Así, y luego guárdelo en una variable.
‫Así que esa es otra forma de crear un nuevo servidor
‫escribiendo incluso un poco menos de código.
‫De acuerdo, al igual que antes, ahora enumeremos el evento
‫de solicitud y especifiquemos nuestra devolución de llamada aquí.
‫Entonces, la primera solución que vamos a utilizar
‫es la más sencilla y directa.
‫Que es simplemente leer el archivo en una variable, y
‫luego, una vez hecho esto, enviarlo al cliente
‫de la forma en que ya sabemos cómo hacerlo.
‫Así que esa es muy simple, y déjame escribir
‫un comentario aquí para eso. Entonces solución
‫uno, y así fs. readFile y luego nuestro archivo de prueba nuevamente.
‫Y luego, una vez que esté listo, llamamos a nuestra función de devolución de
‫llamada en la que tenemos acceso a los datos.
‫Pero primero manejemos el error.
‫Entonces, por ejemplo, en caso de que el archivo no exista, y
‫en ese caso simplemente registramos el error en la consola.
‫Pero de lo contrario, simplemente enviamos estos datos al cliente.
‫Entonces usamos el objeto de respuesta como lo
‫hicimos antes muchas veces, y luego. end y los datos.
‫Entonces, dale un guardado, y esa es la primera
‫y la solución más simple, ¿verdad?
‫Pero antes de que podamos probar esto, también
‫necesitamos iniciar un servidor, ¿verdad? Entonces usamos listen para hacer eso.
‫Y el puerto, el mismo que antes, luego localhost y nuestra función
‫de devolución de llamada.
‫Bien, veamos si esto realmente funciona.
‫Y por supuesto que no, porque en realidad ni siquiera
‫inicié la aplicación.
‫Entonces ahora dice escuchar, y ahora veamos qué
‫pasa aquí.
‫Y aquí vamos. Entonces este archivo es
‫enorme, tiene Node. js es el mejor escrito en
‫él como 10000 veces o algo así, por lo que lleva mucho
‫tiempo hasta que se cargue por completo. Y no estamos realmente interesados
‫en cargar todo, así que detengamos esto aquí y
‫regresemos a nuestro código. Entonces esto funciona bien, la
‫solución que tenemos aquí en este caso, pero el problema
‫es que con esta solución, el nodo en
‫realidad tendrá que cargar todo el archivo en la
‫memoria, porque solo después de que esté listo, puede
‫enviar esos datos . Ahora bien, esto es un problema
‫cuando el archivo es grande, y también cuando hay un montón de
‫solicitudes llegando a su servidor. Debido a que
‫el proceso del nodo se quedará sin recursos muy rápidamente y
‫su aplicación dejará de funcionar, todo se bloqueará y sus usuarios
‫no estarán felices, créanme. Entonces, esta solución
‫aquí funciona cuando solo estamos creando algo
‫pequeño localmente solo para nosotros, por ejemplo.
‫Pero en una aplicación lista para producción, no puede usar un
‫fragmento de código como este. ¿Okey? Así que pasemos a
‫nuestra segunda solución. Y
‫en esa solución, usaremos flujos.
‫Bien, comentemos esta parte y pasemos
‫a la solución número dos.
‫Y la idea aquí es que
‫en realidad no necesitamos leer estos datos del archivo en una variable, ¿verdad?
‫No necesitamos esta variable. Entonces, en lugar de
‫leer los datos en una variable y tener que almacenar
‫esa variable en la memoria, simplemente crearemos un flujo legible.
‫Luego, a medida que recibimos cada fragmento de datos,
‫lo enviamos al cliente como respuesta, que
‫es un flujo de escritura que se recuerda.
‫Permítanme mostrarles cómo podemos usar las transmisiones.
‫Entonces creamos una variable, llamémosla legible aquí, y luego desde
‫el sistema de archivos nuevamente, usamos createReadStream Entonces
‫esto, por supuesto, es pequeño. Y ahora el nombre del archivo
‫que estamos intentando leer. Eso es de nuevo, test-file. TXT.
‫De acuerdo, perfecto. Entonces, esto ahora crea una secuencia a
‫partir de los datos que están en este archivo de texto, que
‫luego podemos consumir pieza por pieza. Así que trozo a trozo.
‫¿Y cómo hacemos eso? Bueno, recuerde de
‫la última conferencia, que cada vez que hay un
‫nuevo dato que podemos consumir, un flujo legible emite
‫el evento de datos. Bien, entonces podemos escuchar eso,
‫tal como aprendimos en la conferencia de eventos.
‫Tan legible. on, data y luego nuestra función de devolución de llamada.
‫Y en nuestra función de devolución de llamada, tenemos acceso a
‫ese dato, es decir, a ese fragmento.
‫Permítanme llamarlo fragmento aquí en nuestra función
‫de devolución de llamada y ahora podemos manejar este dato.
‫Y lo que vamos a
‫hacer con este dato, con este fragmento, es
‫escribirlo en un flujo de escritura, que es la respuesta.
‫Entonces, res. escribe, este trozo. ¿Okey?
‫Recuerde nuevamente que esta respuesta es un
‫flujo de escritura. Entonces, tal como mencioné
‫en el video anterior, ¿verdad? Y ahora podemos usar
‫el método de escritura para enviar cada pieza de datos a ese flujo.
‫Bien, y con esto efectivamente estamos
‫transmitiendo el contenido del archivo directamente al cliente.
‫¿Entiendes la diferencia?
‫Entonces, antes, escribíamos todo a la vez en una variable, y
‫una vez que estaba listo, enviamos esa pieza completa de datos
‫de regreso al cliente. Pero en esta
‫situación, con la corriente, es diferente.
‫Estamos transmitiendo el archivo de manera efectiva, por lo que
‫leemos una parte del archivo y, tan pronto
‫como esté disponible, lo enviamos directamente al cliente, utilizando el método de escritura
‫del flujo de respuesta. Luego, cuando la siguiente
‫pieza esté disponible, esa pieza se enviará y hasta
‫que todo el archivo se lea y se transmita al cliente.
‫Bien, ahora solo para terminar, también tenemos que manejar
‫el evento cuando se leen todos los datos.
‫Entonces, cuando la transmisión básicamente termina de leer los datos
‫del archivo.
‫Entonces, en ese caso, se emitirá el evento final,
‫y tan pronto como eso suceda, lo que vamos a hacer
‫es hacer res. final, ¿de acuerdo? Y usamos este
‫antes, así que terminando la respuesta, lo hicimos antes, ¿verdad?
‫Y ahora, en realidad tiene más sentido, porque nuevamente, la
‫respuesta también es una secuencia, y el método final
‫indica que no se escribirán más datos en esta
‫secuencia de escritura, ¿de acuerdo?
‫Así que aquí todo lo que hicimos fue usar res. terminar con los datos
‫que contiene. Así que no hicimos streaming,
‫todo lo que hicimos al final fue enviar algunos datos.
‫Ahora, en este caso, no estamos
‫pasando nada a este método final, porque ya enviamos todos los
‫datos usando res. escribir, fragmento a fragmento,
‫por lo que cuando la secuencia legible termine
‫de leer su archivo, todo lo que tenemos que hacer es
‫indicar que estamos listos usando res. terminar así, ¿de acuerdo?
‫Por lo tanto, siempre necesitamos usar estos datos y este evento final aquí uno tras
‫otro de esta manera. Porque de
‫lo contrario, la respuesta nunca se
‫enviará realmente al cliente. Bien, sin esta pieza
‫aquí, toda esta solución no funcionaría realmente, ¿de acuerdo?
‫Así que cerremos este, empecemos de nuevo y leamos
‫de nuevo, para que veas que en realidad está funcionando
‫de nuevo, ¿de acuerdo? Ahora esta vez sin los problemas que
‫tuvimos con la primera solución. Detengamos esto aquí y
‫volvamos a nuestro código, porque quiero mostrarles
‫ahora que hay otro evento que podemos escuchar
‫en una secuencia legible, que es el evento de error.
‫Tan legible. on ('error') y en esta función de
‫devolución de llamada tenemos acceso al objeto de error.
‫Bien, en este caso registraremos este error en la consola
‫y luego enviaremos el resultado del archivo no encontrado.
‫Y también podemos establecer el código de estado en
‫un error, por ejemplo, 500. Por lo general, se establece
‫automáticamente en 200, lo que significa que está bien, pero en este caso tenemos un
‫error del servidor, lo que significa que queremos devolver el código 500.
‫Muy bien, ahora vamos ...
‫De hecho, necesito dejar esto de nuevo.
‫Así que veamos qué pasa ahora.
‫Oh, ya tenemos un error aquí
‫mismo, res. el estado no es una función. Y sí,
‫en realidad es statusCode. Así que esta es
‫la forma en que lo escribes en express, así que ya estoy acostumbrado a
‫escribir express tanto que express es un nodo. js que vamos a usar en
‫el resto del curso y
‫en express lo haces así, y ese
‫era el problema. Así que ya estoy un poco
‫acostumbrado a escribir express.
‫Así que regresemos, y sí, ahora vemos el archivo no encontrado, y
‫si abrimos las herramientas de desarrollo, verá nuestro código de error 500 que acabamos de
‫enviar antes, y si vamos a nuestra pestaña de red, intentemos
‫eso de nuevo. también tiene el código de estado aquí.
‫Así que, al igual que vimos en uno de los videos anteriores en
‫otra sección, en realidad. Así es como podemos inspeccionar
‫este tipo de cosas en la pestaña de red.
‫Muy bien, solucionémoslo aquí, guardémoslo, y de acuerdo, esto
‫nuevamente funciona perfectamente, pero todavía hay un problema con
‫este enfoque que les acabo
‫de mostrar. Y el problema es
‫que nuestro flujo legible, por lo que el que
‫estamos usando para leer el archivo desde el disco, es mucho más
‫rápido que enviar el resultado con el flujo grabable de
‫respuesta a través de la red. Y esto abrumará el
‫flujo de respuesta, que no puede manejar todos estos datos entrantes tan rápido.
‫Y este problema se llama contrapresión.
‫Y es un problema real que puede ocurrir en situaciones reales.
‫Entonces, en este caso, la contrapresión ocurre cuando la
‫respuesta no puede enviar los datos tan rápido como los
‫recibe del archivo, ¿tiene sentido?
‫Así que tenemos que arreglar
‫esa solución y encontrar una aún mejor.
‫Entonces, crearemos la solución tres, y
‫esa es en realidad la
‫última, ¿de acuerdo? Así que no hay más soluciones que tres.
‫Entonces, el secreto aquí es usar ese operador de tubería que mencioné
‫en el último video, ¿de acuerdo?
‫Entonces, el operador de tubería está disponible en todas las secuencias legibles y
‫nos permite canalizar la salida de una secuencia legible
‫directamente a la entrada de una secuencia de escritura, ¿de acuerdo?
‫Y eso solucionará el problema de la contrapresión porque
‫automáticamente manejará la velocidad básicamente de los datos
‫que ingresan y la velocidad de los datos que salen.
‫Bien, obtengamos nuestra transmisión legible aquí.
‫De acuerdo, esa es nuestra secuencia legible, y ahora
‫todo lo que tenemos que hacer es tomar nuestra secuencia legible, usar
‫el método de tubería en ella y luego poner una secuencia de escritura y
‫esa es la respuesta. Y eso es todo.
‫Eso es todo lo que tenemos que hacer para esta solución, ¿de acuerdo?
‫Así que siempre funciona así,
‫déjame escribirlo aquí como comentario. Entonces, básicamente, necesitamos una fuente legible, de
‫acuerdo, de nuevo, esto es solo para explicárselo, luego podemos
‫usar la tubería en él, y aquí tendremos que
‫poner un destino de escritura. Entonces, aquí es de donde
‫provienen nuestros datos, y tiene que ser un
‫flujo legible, y esos datos luego podemos canalizarlos a un destino de escritura.
‫Entonces, en este caso, nuestro destino es la respuesta, ¿de acuerdo?
‫Ahora bien, este flujo aquí puede ser un flujo dúplex o
‫de transformación también, pero lo que importa es que podemos
‫escribir en el flujo. Y la respuesta, por supuesto,
‫es una corriente de este tipo. Entonces, por supuesto, podemos escribir
‫la respuesta que se enviará al cliente, ¿de acuerdo?
‫Entonces el operador de tubería resuelve automáticamente el
‫problema de contrapresión que teníamos anteriormente.
‫Y también es una solución mucho más
‫elegante y sencilla. Entonces, lo que hicimos
‫aquí antes fue solo mostrarle todas las formas en
‫que podemos usar los métodos y eventos de transmisión para crear este tipo
‫de solución y, por supuesto, tienen muchos casos de uso,
‫pero en un problema como este, la tubería El operador es
‫en realidad la mejor solución. Detrás de escena, en realidad, hace
‫algo como esto aquí, pero
‫nuevamente de una manera mucho más directa para que
‫escribamos, porque maneja todas las cosas
‫internamente detrás de escena. Así que creo que la
‫tubería aquí es en realidad la forma más fácil de consumir y
‫escribir secuencias, a menos que, por supuesto, como mencioné,
‫necesitemos soluciones más personalizadas. Y luego, tenemos que
‫usar estas herramientas más complicadas como estos eventos y
‫métodos que les mostré antes. Muy bien, para
‫terminar, salgamos del proceso aquí, empecemos de nuevo y, por
‫supuesto, veamos si todavía funciona, lo cual funciona.
‫Y así, nuestro trabajo está hecho aquí. Así que hemos terminado con esta
‫conferencia y estamos listos para pasar directamente a la siguiente.