Error Handling di Node.js
Membedakan error operasional dan bug, membuat error kustom, serta menangani unhandledRejection dan uncaughtException.
Dua jenis kesalahan
| Operasional | Programmer (bug) | |
|---|---|---|
| Contoh | Database mati, berkas tak ada, input tak valid, timeout jaringan | Memanggil fungsi yang undefined, salah ketik properti |
| Bisa dihindari? | Tidak — selalu mungkin terjadi | Ya, dengan kode yang benar |
| Penanganan | Tangani dengan wajar (coba lagi, pesan ramah, kode status) | Perbaiki kodenya; jangan menutupinya |
Cara error muncul di Node
- throw dalam kode sinkron → tangkap dengan
try/catch. - callback error-first → periksa argumen
err. - Promise reject /
async→.catchatautry/catchdenganawait. - Event 'error' pada EventEmitter/stream → pasang pendengar
error.
Error kustom
Jangan melempar string. Selalu lempar objek Error (agar punya stack trace). Buat turunan untuk membedakan jenis kegagalan:
class ValidasiError extends Error {
constructor(field, pesan) {
super(pesan);
this.name = 'ValidasiError';
this.field = field;
this.status = 400; // berguna untuk respons HTTP
}
}
function daftar({ nama, email }) {
if (!email) throw new ValidasiError('email', 'email wajib diisi');
return { nama, email };
}
try {
daftar({ nama: 'Dina' });
} catch (err) {
if (err instanceof ValidasiError) {
console.log(`${err.name}: ${err.message} (field: ${err.field})`);
} else {
throw err; // yang tak dikenal: lempar ulang, jangan telan!
}
}
Error cause (rantai penyebab)
try { await bacaKonfig(); }
catch (err) { throw new Error('Gagal memulai aplikasi', { cause: err }); }
Jaring pengaman tingkat proses
process.on('unhandledRejection', (reason) => {
console.error('Promise ditolak tanpa catch:', reason);
});
process.on('uncaughtException', (err) => {
console.error('Error tak tertangkap:', err);
process.exit(1); // keadaan proses mungkin rusak: keluar & biarkan pengawas me-restart
});
Penting: ini jaring pengaman untuk pencatatan, bukan cara menangani error. Setelah uncaughtException, keadaan aplikasi tidak bisa dipercaya; praktik terbaik: catat lalu keluar, dan biarkan pengawas proses (pm2, Docker, systemd) menjalankannya ulang. Sejak Node 15, unhandledRejection yang tidak ditangani akan mematikan proses.
Jangan menelan error
catch (e) {} // ❌ error hilang tanpa jejak
catch (e) { console.log(e) } // ⚠ dicatat tapi program lanjut seolah baik-baik saja
Tangani (pulihkan), ubah menjadi error yang lebih bermakna, atau lempar ulang.
Praktik baik
- Validasi input di tepi sistem (permintaan masuk) dan beri pesan yang jelas.
- Catat error dengan konteks (ID permintaan, parameter) — tetapi jangan mencatat rahasia.
- Jangan bocorkan stack trace atau detail internal ke pengguna.
- Gunakan
finallyuntuk membersihkan sumber daya (tutup koneksi, hapus berkas sementara).