Búferes y flujos en Node.js
Artículo básico sobre la gestión de búferes y flujos en Nodejs. Conceptos e implementaciones.
Introducción
El concepto de búferes y flujos en el mundo de la informática y las comunicaciones no es algo nuevo. Muchas veces hemos escuchado la palabra Streaming cuando, por ejemplo, un famoso jugador de videojuegos te invita a seguir una transmisión en vivo, o cuando una persona transmite una transmisión en vivo a través de Instagram o Facebook. La transmisión de videos u otros sigue los mismos principios que veremos a continuación.
Concepto de buffer
Un búfer es un espacio en la memoria (generalmente RAM) que almacena temporalmente datos binarios. El propósito de este espacio es ayudar a cualquier entidad en ejecución a no perder datos durante una transferencia utilizando un sistema FIFO.
Búfer en Nodejs
En Nodejs podemos manipular estos espacios de memoria con el módulo llamado Buffer integrado en su núcleo. Los búferes se usan ampliamente cuando se trabaja con datos binarios a nivel de red.
Recordemos que muchos de los módulos y funcionalidades de Nodejs funcionan implícitamente en función de eventos y manipulación de Buffer/Streams, como el core File System o los módulos HTTP que almacenan el flujo de datos temporal en un Buffer.
Aquí hay algunas características importantes de Buffers:
- Los búferes se almacenan en una secuencia de números enteros.
- Una vez creados, no se pueden cambiar de tamaño.
Aquí hay un ejemplo de cómo crear un Buffer en Nodejs usando la clase Buffer:
const { Buffer } = require('buffer'); const buf6 = Buffer.from('hello'); console.log(buf6);
El fragmento de código anterior crea un búfer que contiene los bytes codificados en UTF-8 para la cadena “hola”, esto imprime el siguiente resultado en la consola:
<Buffer 68 65 6c 6c 6f> hello// [0x68, 0x65, 0x6c, 0x6c, 0x6f] (hexadecimal notation)
Una vez guardada la información, podemos leer perfectamente el contenido almacenado, aquí un ejemplo:
const text = buf6.toString(); console.log(text); // hello
La mayoría de los lenguajes de programación han incorporado en su núcleo un conjunto de funcionalidades y clases que te permiten trabajar con Buffers y Streams de forma sencilla.
Concepto de corriente
Son flujos de información que se utilizan en la transmisión de datos binarios. También son una forma de manejar las comunicaciones de red o cualquier tipo de intercambio de datos de ida y vuelta de manera eficiente, al dividir la información en partes más pequeñas.
Estas son algunas características importantes de Streams:
- Las secuencias funcionan secuencialmente.
- La información se transmite a través de “chunks” (piezas).
- Los flujos se basan en búferes para administrar el contenido.
Destaquemos que los Streams son una de las estrategias más efectivas para procesar grandes cantidades de información. Por ejemplo, cuando el tamaño de un archivo es mayor que el espacio libre en la memoria, el uso de piezas más pequeñas permite leerlo.
Los servicios de streaming como Netflix u otros no te obligan a descargar el video de una sola vez, ya que sería un proceso muy costoso para el dispositivo. En cambio, estos servicios le envían la información en un flujo continuo de fragmentos, lo que le permite reproducir el contenido de inmediato.
Transmitir en Nodejs
Nodejs tiene un módulo llamado stream que nos ayuda con la manipulación de estos flujos, pero dependiendo del caso usaremos algún tipo de stream.
En general, hay 4 tipos de Streams en Nodejs:
- Writable: Flujos en los que podemos escribir datos.
- Legible: flujos desde los que se pueden leer los datos.
- Dúplex: flujos que se leen y escriben.
- Transform: flujos que pueden modificar o transformar datos a medida que se escriben y leen.
Si ya hemos trabajado antes con Nodejs, seguro que nos hemos dado cuenta de que, por ejemplo, cualquier servidor HTTP basado en Nodejs, funciona con la lectura de Streams en la petición al servidor (Readable) y la respuesta al cliente funciona con la escritura de Streams (Writable ). Este y otros módulos principales funcionan de la misma manera.
Aquí hay un ejemplo de cómo crear una transmisión en Nodejs de tipo legible y enviar datos:
const Stream = require('stream'); const readableStream = new Stream.Readable();readableStream.push('Hello'); readableStream.push(' '); readableStream.push('World'); readableStream.push(null);async function getContentReadStream(readable) { for await (const chunk of readable) { console.log(chunk); console.log(chunk.toString()); } }getContentReadStream(readableStream);
Esto imprime el siguiente resultado en la consola:
<Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64> Hello World
Destacando que al crear un objeto de tipo stream, automáticamente se crea un búfer de soporte para la manipulación. El tamaño del chunk o buffer se puede configurar previamente.
Aquí hay una imagen complementaria de la relación Buffers and Streams:
Recursos Búfers y flujos de Nodejs
- Buffer API: Documentación y características de los Buffers.
- Stream API: Documentación y características de los Streams.
Finalizando
El manejo de búfer y transmisión son las características principales más poderosas de Nodejs. Las operaciones de entrada y salida se optimizan bajo secuencias canalizadas fáciles de procesar, lo que ayuda al sistema a consumir grandes cantidades de información sin arriesgar el procesamiento.
Gracias por llegar hasta aquí, si encuentras esto útil no olvides aplaudir 👍🏼suscribirse para recibir más contenido.
Si necesita ayuda adicional, por favor contácteme.
Si le interesa, puede echar un vistazo a algunos de los otros artículos que he escrito recientemente sobre AWS y Laravel: