Menu

fs/promises Node.js: API File System dengan async/await

fs/promises adalah versi promise dari module fs milik Node: readFile, writeFile, readdir, stat, mkdir, rm, dan rename semuanya mengembalikan promise yang kamu await, dan error ditangkap dengan try/catch.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

fs/promises adalah versi berbasis promise dari module fs milik Node. Fungsi-fungsinya (readFile, writeFile, readdir, stat, mkdir, rm, rename, dan lainnya) mengembalikan promise alih-alih menerima callback, jadi kamu await fungsinya dan menangkap error dengan try/catch. Import dengan require('fs/promises') atau import fs from 'fs/promises'.

Hasilnya [ 'write docs', 'ship it' ]: setiap await menunggu satu operasi sebelum baris berikutnya berjalan, jadi append selalu terjadi setelah penulisan pertama. Di ES module, await bisa dipakai di tingkat atas; di CommonJS, bungkus kodenya dalam fungsi async.

Fungsi yang paling sering kamu pakai

Namanya sama dengan API callback, hanya tanpa callback. Halaman readFile dan writeFile membahas keduanya secara detail.

FungsiFungsinyaResolve menjadi
readFile(path, 'utf8')Membaca seluruh fileIsi file
writeFile(path, data)Membuat atau mengganti fileundefined
appendFile(path, data)Menambah di akhirundefined
readdir(path)Menampilkan isi folderArray berisi nama
stat(path)Ukuran, tanggal, file atau folderObject Stats
mkdir(path, { recursive: true })Membuat folderFolder pertama yang dibuat, atau undefined
rename(from, to)Memindahkan atau mengganti namaundefined
rm(path, { recursive: true, force: true })Menghapus file atau folderundefined

Menampilkan isi folder dengan readdir dan stat

readdir hanya mengembalikan nama. Panggil stat untuk setiap nama untuk mendapat ukurannya atau membedakan file dari folder, atau berikan { withFileTypes: true } untuk mendapat entri yang sudah tahu tipenya.

Perulangannya mencetak README.md 6 bytes, notes.txt 3 bytes, dan src folder. stat reject dengan ENOENT untuk path yang tidak ada, jadi ia bisa dipakai sebagai pengecekan keberadaan yang cepat saat kamu juga butuh detailnya.

Mengganti nama, memindahkan, dan menghapus

rename bisa mengganti nama sekaligus memindahkan file (di drive yang sama). rm menghapus; ia butuh recursive: true untuk folder yang ada isinya, dan force: true supaya tidak gagal saat path-nya sudah tidak ada.

File-nya pindah dari drafts ke published dengan nama barunya, dan setelah rm, folder blog hanya berisi published. Hapus force: true dari rm kedua dan ia reject dengan ENOENT.

Menangani error dengan try/catch

Operasi yang gagal membuat promise-nya reject. Dengan await, reject itu menjadi exception yang kamu tangkap seperti exception lain. code milik error memberi tahu apa yang salah.

Panggilan pertama tidak menemukan file dan mengembalikan []; panggilan kedua mencetak Ada. Kode yang perlu kamu kenal: ENOENT (file tidak ada), EEXIST (sudah ada), EISDIR (folder di tempat yang seharusnya file), ENOTEMPTY (folder masih ada isinya), dan EACCES (tidak ada izin).

Promise yang tidak kamu await dan tidak kamu .catch() menjadi unhandled rejection saat gagal, dan Node berhenti dengan error. Await setiap panggilan, atau kembalikan promise-nya ke pemanggil yang meng-await-nya.

Membaca beberapa file sekaligus dengan Promise.all

Perulangan for dengan await membaca file satu per satu. Saat pembacaan tidak saling bergantung, mulai semuanya lalu tunggu sekali dengan Promise.all: disk mengerjakannya bersamaan.

Promise.all menjaga urutan array input, jadi hasilnya [ 'alpha', 'beta', 'gamma' ] tidak peduli pembacaan mana yang selesai duluan, dan panjang gabungannya 14. Ganti 'b.txt' di array menjadi 'x.txt' dan seluruh await reject dengan ENOENT.

Kalau kamu butuh setiap hasil walaupun sebagian pembacaan gagal, pakai Promise.allSettled; halaman promise membahas keduanya.

Kesalahan umum

Tertukar antara dua module. require('fs').readFile butuh callback; require('fs/promises').readFile mengembalikan promise. Memanggil versi callback tanpa callback melempar The "cb" argument must be of type function.

Lupa await. const text = fs.readFile(...) adalah promise yang masih pending, dan text.split melempar text.split is not a function.

Penulisan paralel ke satu file. Promise.all dengan beberapa penulisan ke path yang sama bisa meninggalkan isi yang tercampur. Jalankan secara berurutan.

Pertanyaan yang sering diajukan

Apa bedanya fs.promises dan fs/promises?

Tidak ada. require('fs').promises dan require('fs/promises') adalah object yang sama. Path fs/promises (atau node:fs/promises) adalah cara yang umum untuk meng-import-nya sekarang.

Apakah ada existsSync di fs/promises?

Tidak. API promise punya access, yang reject saat path-nya tidak ada, tetapi pola yang umum adalah langsung memanggil operasi yang kamu butuhkan lalu menangkap ENOENT. existsSync dari module fs biasa tetap bisa dipakai untuk pengecekan cepat.

Apakah fs/promises lebih lambat dari API callback?

Sedikit, karena overhead promise, tetapi tidak berarti dibanding waktu disk. Pilih berdasarkan keterbacaan; API promise adalah yang dipakai sebagian besar kode baru.

Bagaimana cara mengubah fungsi fs berbasis callback menjadi promise?

Jarang perlu, karena fs/promises sudah mencakup fungsi-fungsi file. Untuk API callback lain, util.promisify(fn) mengembalikan versi yang mengembalikan promise.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai