Stream: Memproses Data Sedikit demi Sedikit

Readable, Writable, Transform, pipe, dan pipeline: cara Node menangani data besar dengan memori kecil.

Part 14 dari 24 ± 40 menit Gratis

Masalah: berkas 2 GB

fs.readFile memuat seluruh berkas ke memori. Berkas 2 GB berarti 2 GB RAM — server bisa kehabisan memori. Stream memproses data dalam potongan kecil (chunk): baca sedikit, proses, kirim, lanjut. Memori yang dipakai tetap kecil, berapa pun ukuran datanya. Analogi: menuang air dari galon lewat selang ke gelas-gelas, bukan mengangkat seluruh galon.

Empat jenis stream

JenisFungsiContoh
ReadableSumber datafs.createReadStream, request HTTP masuk
WritableTujuan datafs.createWriteStream, response HTTP
DuplexKeduanyaSoket TCP
TransformDuplex yang mengubah dataKompresi (gzip), enkripsi, parsing

Membaca stream

const fs = require('fs');

const r = fs.createReadStream('besar.txt', { encoding: 'utf8', highWaterMark: 64 * 1024 });
let n = 0;
r.on('data', (chunk) => { n++; /* proses potongan */ });
r.on('end', () => console.log('selesai,', n, 'chunk'));
r.on('error', (err) => console.error(err.message));

highWaterMark menentukan ukuran chunk (default 64 KB untuk berkas). Event penting: data, end, error, close.

pipe dan pipeline

// Menyalin berkas tanpa memuatnya ke memori
const { pipeline } = require('stream');

pipeline(
  fs.createReadStream('asal.txt'),
  fs.createWriteStream('salinan.txt'),
  (err) => {
    if (err) console.error('Gagal:', err.message);
    else console.log('Selesai');
  }
);

pipeline lebih aman daripada a.pipe(b): ia meneruskan error dan membersihkan semua stream bila salah satunya gagal. Versi Promise: const { pipeline } = require('stream/promises'); await pipeline(a, b, c);

Transform: mengubah data di tengah jalan

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

const hurufBesar = new Transform({
  transform(chunk, encoding, callback) {
    callback(null, chunk.toString().toUpperCase());   // (error, data keluar)
  },
});

pipeline(fs.createReadStream('in.txt'), hurufBesar, fs.createWriteStream('OUT.txt'), (err) => { /* ... */ });

Readable.from: stream dari iterable

const { Readable } = require('stream');
const r = Readable.from(['halo ', 'dunia']);
for await (const potongan of r) console.log(potongan);

Writable sendiri

const { Writable } = require('stream');
const hasil = [];
const kumpul = new Writable({
  write(chunk, enc, callback) { hasil.push(chunk.toString()); callback(); },
});

Backpressure

Jika sumber lebih cepat daripada tujuan, data menumpuk di memori. Stream memiliki mekanisme backpressure: write() mengembalikan false saat buffer penuh, dan sumber berhenti sampai event drain. pipe dan pipeline mengurusnya otomatis — alasan lain mengapa jangan menulis loop write manual tanpa memeriksa nilai kembaliannya.

Di mana stream dipakai?

  • Mengunggah/mengunduh berkas besar, streaming video.
  • Mengirim response HTTP sedikit demi sedikit.
  • Membaca log atau CSV besar baris demi baris.
  • Kompresi (zlib), enkripsi.

Praktikkan langsung, gratis

Tulis dan jalankan kode langsung di browser, dapatkan penilaian otomatis. Daftar gratis kapan saja untuk menyimpan progres dan meraih sertifikat.

Coba latihan sekarang, tanpa daftar
Bagikan: WhatsApp Facebook LinkedIn X