Node.js Streams: Procesamiento eficiente de datos

Aprende a trabajar con streams en Node.js para manejar grandes volúmenes de datos de manera eficiente

CodeCraft Master
17 de febrero de 2026
11 min
7456 views

Node.js Streams: Procesamiento eficiente de datos

Los Streams son una característica fundamental de Node.js que te permite procesar datos de manera eficiente, especialmente cuando trabajas con grandes volúmenes.

¿Por qué usar Streams?

// ❌ Malo: Carga todo el archivo en memoria
const fs = require('fs');
const data = fs.readFileSync('archivo-grande.txt');
console.log(data);

// ✅ Bueno: Procesa el archivo en chunks
const stream = fs.createReadStream('archivo-grande.txt');
stream.on('data', (chunk) => {
  console.log(chunk);
});

Tipos de Streams

1. Readable Streams

const { Readable } = require('stream');

const readable = new Readable({
  read(size) {
    this.push('datos ');
    this.push('en ');
    this.push('chunks\n');
    this.push(null); // No más datos
  }
});

readable.on('data', (chunk) => {
  console.log(chunk.toString());
});

2. Writable Streams

const { Writable } = require('stream');
const fs = require('fs');

const writable = fs.createWriteStream('output.txt');

writable.write('Primera línea\n');
writable.write('Segunda línea\n');
writable.end('Última línea\n');

writable.on('finish', () => {
  console.log('Escritura completa');
});

3. Duplex Streams

const { Duplex } = require('stream');

const duplex = new Duplex({
  read(size) {
    this.push('datos de lectura\n');
    this.push(null);
  },
  write(chunk, encoding, callback) {
    console.log('Escribiendo:', chunk.toString());
    callback();
  }
});

4. Transform Streams

const { Transform } = require('stream');

const uppercase = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

process.stdin
  .pipe(uppercase)
  .pipe(process.stdout);

Pipe: Conectando Streams

const fs = require('fs');
const zlib = require('zlib');

// Leer archivo, comprimir y guardar
fs.createReadStream('input.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('input.txt.gz'));

Ejemplo práctico: Procesador de CSV

const fs = require('fs');
const { Transform } = require('stream');

class CSVParser extends Transform {
  constructor() {
    super({ objectMode: true });
    this.header = null;
  }

  transform(chunk, encoding, callback) {
    const lines = chunk.toString().split('\n');
    
    lines.forEach((line, index) => {
      if (!this.header) {
        this.header = line.split(',');
      } else if (line.trim()) {
        const values = line.split(',');
        const obj = {};
        this.header.forEach((key, i) => {
          obj[key] = values[i];
        });
        this.push(obj);
      }
    });
    
    callback();
  }
}

fs.createReadStream('data.csv')
  .pipe(new CSVParser())
  .on('data', (obj) => {
    console.log(obj);
  });

Backpressure: Manejo de flujo

const fs = require('fs');

const readable = fs.createReadStream('input.txt');
const writable = fs.createWriteStream('output.txt');

readable.on('data', (chunk) => {
  const canContinue = writable.write(chunk);
  
  if (!canContinue) {
    // El buffer está lleno, pausar lectura
    readable.pause();
  }
});

writable.on('drain', () => {
  // El buffer se vació, continuar lectura
  readable.resume();
});

Stream de API HTTP

const https = require('https');
const fs = require('fs');

https.get('https://example.com/largefile.zip', (response) => {
  const file = fs.createWriteStream('downloaded.zip');
  
  let downloadedSize = 0;
  const totalSize = parseInt(response.headers['content-length'], 10);
  
  response.on('data', (chunk) => {
    downloadedSize += chunk.length;
    const progress = (downloadedSize / totalSize * 100).toFixed(2);
    console.log(`Descargado: ${progress}%`);
  });
  
  response.pipe(file);
  
  file.on('finish', () => {
    file.close();
    console.log('Descarga completa');
  });
});

Pipeline: Manejo de errores

const { pipeline } = require('stream');
const fs = require('fs');
const zlib = require('zlib');

pipeline(
  fs.createReadStream('input.txt'),
  zlib.createGzip(),
  fs.createWriteStream('input.txt.gz'),
  (err) => {
    if (err) {
      console.error('Pipeline falló:', err);
    } else {
      console.log('Pipeline exitoso');
    }
  }
);

Conclusión

Los Streams son esenciales para aplicaciones Node.js eficientes. Te permiten procesar grandes cantidades de datos sin saturar la memoria, haciendo tu aplicación más escalable y performante.

C

CodeCraft Master

Desarrollador Full Stack apasionado por compartir conocimiento. Escribo sobre JavaScript, TypeScript, React y desarrollo web moderno.

Artículos Relacionados

Únete a nuestro boletín

Recibe contenido exclusivo de desarrollo web directamente en tu bandeja de entrada.

  • Contenido exclusivo de desarrollo web

  • Actualizaciones semanales

  • Tips y trucos

  • Sin spam, solo contenido de calidad

Al suscribirte, aceptas recibir correos electrónicos. Puedes cancelar tu suscripción en cualquier momento.