Belajar Node.js - File I/O dan Stream Dasar
Episode 5 of 23

Belajar Node.js - File I/O dan Stream Dasar

Episode ini membedah file I/O modern dengan fs/promises dan stream untuk menangani file besar tanpa membebani memori. Kalian juga belajar pipeline untuk menyambung stream dan readline untuk memproses file baris per baris.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Di episode 3 kita membaca file dengan versi Sync yang memblokir thread utama. Untuk aplikasi server, itu bukan pilihan. Node.js menyediakan dua pendekatan yang tepat: API Promise dari fs/promises untuk operasi file biasa, dan stream untuk file besar atau data yang mengalir terus-menerus.

Episode 5 membahas keduanya. Kalian akan melihat fs/promises dengan async/await yang bersih, konsep stream yang hemat memori, pipeline untuk menyambung stream, serta readline untuk memproses file log baris per baris — pola yang sangat umum di dunia nyata.

File I/O dengan fs/promises

Async/Await yang Bersih

Modul node:fs/promises menyediakan seluruh fungsi fs dalam bentuk Promise, tanpa akhiran Sync dan tanpa callback yang bersarang:

JSBaca tulis dengan fs/promises
import { readFile, writeFile, mkdir } from "node:fs/promises";
 
await mkdir("data", { recursive: true });
await writeFile("data/catatan.txt", "Belajar stream");
const isi = await readFile("data/catatan.txt", "utf8");
console.log(isi);

writeFile dan readFile mengembalikan Promise sehingga bisa dipakai dengan await. Karena ESM mendukung top-level await (episode 4), contoh di atas bisa berjalan langsung. Opsi recursive: true pada mkdir membuat folder tanpa error jika sudah ada.

Menangani Error dengan Try/Catch

Berbeda dengan callback yang memakai pola error-first, versi Promise memakai try/catch standar:

JSTry/catch untuk file I/O
import { readFile } from "node:fs/promises";
 
try {
  const isi = await readFile("tidak-ada.txt", "utf8");
  console.log(isi);
} catch (err) {
  console.error("Gagal membaca:", err.message);
}

await readFile("tidak-ada.txt", "utf8") melempar error ENOENT ketika file tidak ditemukan, dan blok catch menangkapnya. Pola ini jauh lebih mudah dibaca daripada callback bersarang — detail lebih lanjut tentang error akan kita bahas di episode 6.

Konsep Dasar Stream

Mengapa Stream Penting

Membaca file 2 gigabyte dengan readFile akan menaruh seluruh isinya di memori — risiko OOM. Stream memecah masalah ini: data dibaca dalam potongan (chunk) kecil, diproses, lalu dilepas. Memori tetap rendah berapa pun ukuran file.

Stream di Node.js punya empat tipe:

  • Readable: sumber data, misalnya createReadStream.
  • Writable: tujuan data, misalnya createWriteStream.
  • Duplex: dua arah, misalnya socket TCP.
  • Transform: memproses data di tengah, misalnya zlib.createGzip.

Menyalin File dengan Pipeline

pipeline dari node:stream/promises menyambungkan stream sekaligus menangani error dan penutupan dengan benar:

JSSalin file via stream
import { createReadStream, createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";
 
await pipeline(
  createReadStream("akses.log"),
  createWriteStream("salinan.log"),
);
console.log("Selesai streaming");

pipeline(createReadStream("akses.log"), createWriteStream("salinan.log")) mengalirkan data dari sumber ke tujuan dalam potongan kecil. Gunakan pipeline daripada metode .pipe() langsung — pipeline memastikan aliran dibersihkan dan error diteruskan dengan benar.

Memproses Data dengan Transform dan Readline

Menyambung Transform Stream

Untuk memproses setiap potongan di tengah aliran, sisipkan stream Transform:

JSStream dengan transform
import { createReadStream, createWriteStream } from "node:fs";
import { Transform } from "node:stream";
import { pipeline } from "node:stream/promises";
 
const uppercase = new Transform({
  transform(chunk, enc, callback) {
    callback(null, chunk.toString().toUpperCase());
  },
});
 
await pipeline(
  createReadStream("data.txt"),
  uppercase,
  createWriteStream("hasil.txt"),
);

Objek Transform di atas mengubah setiap potongan menjadi huruf kapital sebelum diteruskan ke tujuan. Antara stream sumber dan tujuan bisa disisipkan banyak transform — inilah dasar dari pipeline kompresi, enkripsi, dan parsing log.

Readline untuk Baris per Baris

Ketika kalian perlu memproses file baris per baris — misalnya log atau CSV — node:readline adalah pilihan tepat:

JSProses file baris per baris
import { createReadStream } from "node:fs";
import { createInterface } from "node:readline";
 
const rl = createInterface({
  input: createReadStream("data.txt"),
});
 
for await (const baris of rl) {
  console.log("Baris:", baris);
}

createInterface({ input: createReadStream("data.txt") }) membungkus stream file menjadi antarmuka baris, dan loop for await memproses setiap baris satu per satu. Pola ini dipakai luas untuk agregasi log dan import data dalam jumlah besar.

Kapan Memilih readFile vs Stream

Panduan Praktis

Aturan memilih cukup sederhana:

  • File kecil yang dibaca sekali: pakai readFile dari fs/promises.
  • File besar atau data yang tidak diketahui ukurannya: pakai stream.
  • File yang diproses baris per baris: pakai readline.
  • Memproses setiap potongan: sisipkan Transform dalam pipeline.

Di dunia nyata, server log, uploader file, dan media streaming hampir selalu memakai stream. Memahami kapan beralih dari readFile ke stream adalah salah satu pembeda antara kode pemula dan kode production.

Penutup

Inti yang harus dibawa pulang:

  • fs/promises menyediakan file I/O dengan async/await yang bersih.
  • Stream memproses data dalam potongan kecil sehingga hemat memori.
  • pipeline menyambung stream sekaligus menangani error.
  • Transform memodifikasi data di tengah aliran.
  • readline memproses file baris per baris dengan loop for await.
  • File kecil pakai readFile; file besar dan data mengalir pakai stream.

Di episode 6 selanjutnya kita akan membahas penanganan error dan debugging di Node — pola try/catch, error-first callback, event error, uncaught exception, serta debugging dengan inspector dan DevTools. Ini keterampilan yang menyelamatkan kalian setiap hari sebagai pengembang backend.

Belajar Node.js - File I/O dan Stream Dasar | Belajar Node.js