Pengenalan Penanganan Eror
Ketika mengembangkan sebuah aplikasi, sebagus apa pun kita membuatnya, akan selalu ada kemungkinan terjadi error atau crash. Entah terjadi karena kesalahan kita dalam menyusun logika kode, kesalahan input dari user, atau banyak alasan lainnya.
Ketika aplikasi mengalami eror, aplikasi akan berhenti dan program setelahnya tidak akan dieksekusi.
Sebagai developer, tentunya menjadi tugas kita untuk memastikan aplikasi tetap berjalan bagaimana pun kondisinya. Termasuk mengatasi ketika terjadi eror. Lantas bagaimana?
Pada modul ini, kita akan mempelajari beberapa hal, seperti:
- Bagaimana menangani error yang mungkin muncul pada aplikasi supaya tidak crash.
- Membuat custom error untuk menandai error yang tidak tersedia pada JavaScript.
Try and Catch
Untuk menangani eror pada JavaScript, gunakan try dan catch. Penulisan kode try-catch untuk menangani eror adalah seperti ini:
try { // kode } catch (error) { // error handling }
Taruh kode yang berpeluang menimbulkan eror di dalam blok try. Apabila terjadi eror di dalam blok kode try, maka ia akan ditangkap dan ditangani oleh blok kode catch. Sementara, jika tidak terjadi eror pada kode, maka blok catch akan diabaikan.
try { console.log("Awal blok try"); console.log("Akhir blok try"); } catch (error) { console.log("Tidak terjadi eror, maka kode ini diabaikan"); } /* output Awal blok try Akhir blok try */
Kode di dalam blok try di atas tidak akan menghasilkan eror, sehingga kode di dalam blok catch akan diabaikan dan tidak dijalankan. Berikut ini adalah contoh kode yang menghasilkan eror:
try { console.log("Awal blok try"); // (1) errorCode; // (2) console.log("Akhir blok try"); // (3) } catch (error) { console.log("Terjadi error!"); // (4) } /* output Awal blok try Terjadi error! */
Baris kode (2) akan menghasilkan eror. Eksekusi kode di dalam blok try akan dihentikan, sehingga baris kode (3) tidak akan tereksekusi. Kemudian kode akan dilanjutkan ke baris (4) atau blok catch.
Selamat! Anda telah berhasil menangani eror dan menghindarkan aplikasi dari crash (Cobalah untuk menghapus sintaks try-catch dan melihat bagaimana aplikasi akan crash). Namun, bagaimana kita bisa tahu apa yang menyebabkan suatu program mengalami eror? Jika ada informasi yang jelas tentunya akan sangat membantu kita atau pengguna nantinya bukan?
Sekarang perhatikan blok catch. Di sana catch memiliki satu parameter bernama error (nama variabel bisa diubah). Variabel error tersebut merupakan sebuah object yang menyimpan detail informasi dari error yang terjadi.
Object error memiliki beberapa properti utama di dalamnya, yaitu:
- name : Nama error yang terjadi.
- message : Pesan tentang detail error.
- stack : Informasi urutan kejadian yang menyebabkan error. Umumnya digunakan untuk debugging karena terdapat informasi baris mana yang menyebabkan error.
Sekarang mari kita coba untuk mengubah kode dan menampilkan properti error di atas.
try { console.log("Awal blok try"); // (1) errorCode; // (2) console.log("Akhir blok try"); // (3) } catch (error) { console.log(error.name); console.log(error.message); console.log(error.stack); } /* output Awal blok try ReferenceError errorCode is not defined ReferenceError: errorCode is not defined at file:///home/dicoding/Playground/javascript/CoffeeMachine/error.js:3:5 at ModuleJob.run (internal/modules/esm/module_job.js:152:23) at async Loader.import (internal/modules/esm/loader.js:166:24) at async Object.loadESM (internal/process/esm_loader.js:68:5) */
Dari informasi di atas, kita bisa tahu bahwa error yang muncul adalah ReferenceError karena errorCode dianggap sebagai sebuah variabel atau nilai yang tidak terdefinisi.
try-catch-finally
Selain try dan catch, ada satu blok lagi yang ada dalam mekanisme error handling pada JavaScript, yaitu finally. Blok finally akan tetap dijalankan tanpa peduli apa pun hasil yang terjadi pada blok try-catch.
try { console.log("Awal blok try"); console.log("Akhir blok try"); } catch (error) { console.log("Baris ini diabaikan"); } finally { console.log("Akan tetap dieksekusi"); } /* output Awal blok try Akhir blok try Akan tetap dieksekusi */
Throwing Errors
Sekarang kita lihat implementasi try-catch pada kasus yang lebih umum. Perhatikan kode berikut:
let json = '{ "name": "Yoda", "age": 20 }'; try { let user = JSON.parse(json); console.log(user.name); console.log(user.age); } catch (error) { console.log(error.name); console.log(error.message); }
Pada kode di atas, fungsi JSON.parse akan melakukan parsing atau konversi dari variabel json (String) menjadi sebuah object. Skenario seperti di atas akan banyak kita temui ketika melakukan request ke API.
Jalankan kode di atas pada text editor Anda. Seharusnya aplikasi berjalan lancar tanpa menimbulkan eror.
Lalu, bagaimana jika json string tidak sesuai dengan format object JavaScript?
let json = '{ bad json }'; try { let user = JSON.parse(json); console.log(user.name); console.log(user.age); } catch (error) { console.log(error.name); console.log(error.message); } /* output SyntaxError Unexpected token b in JSON at position 2 */
Apabila json tidak sesuai format, maka JSON.parse akan menimbulkan eror. Eror tersebut akan ditangkap oleh blok catch dan kode di dalamnya yang akan dieksekusi.
Lalu, bagaimana jika json yang didapat adalah seperti ini?
let json = '{ "age": 20 }'; try { let user = JSON.parse(json); console.log(user.name); // undefined console.log(user.age); // 20 } catch (error) { console.log(error.name); console.log(error.message); }
Secara sintaksis, kode di atas tidak menimbulkan eror, sehingga blok catch akan diabaikan. Namun, tidak adanya properti name pada json sebenarnya sama saja dengan eror karena akan berdampak pada jalannya program kita.
Untuk mengatasinya, kita bisa menggunakan throw. Operator ini akan “melemparkan” eror pada program, sehingga eksekusi kode akan masuk pada blok catch. Berikut ini adalah contoh mengimplementasikan throw untuk menimbulkan eror kita sendiri:
let json = '{ "age": 20 }'; try { let user = JSON.parse(json); if (!user.name) { throw new SyntaxError("'name' is required."); } console.log(user.name); // undefined console.log(user.age); // 20 } catch (error) { console.log(`JSON Error: ${error.message}`); } /* output JSON Error: 'name' is required. */
Ketika properti user.name tidak memiliki nilai, maka program akan menghasilkan SyntaxError. Di dalamnya kita bisa menentukan pesan yang dapat membantu menjelaskan apa eror yang terjadi.
Sekarang kita telah mengetahui ada banyak kemungkinan eror yang bisa muncul dalam sebuah program. Tentunya akan sangat membantu jika kita bisa memberikan pesan yang sesuai kepada pengguna atau kepada diri kita sendiri untuk menemukan kesalahan dengan lebih mudah.
Sekarang anggaplah json sudah sesuai, tetapi ternyata ada eror lain yang terjadi, misalnya karena variabel yang belum terdefinisi.
let json = '{ "name": "Yoda", "age": 20 }'; try { let user = JSON.parse(json); if (!user.name) { throw new SyntaxError("'name' is required."); } errorCode; console.log(user.name); // Yoda console.log(user.age); // 20 } catch (error) { console.log(`JSON Error: ${error.message}`); } /* output JSON Error: errorCode is not defined */
Eror berhasil ditangani, tetapi konsol tetap menampilkan pesan “JSON Error”, lantas bagaimana kita bisa menampilkan pesan eror sesuai eror yang muncul?
Jawabannya adalah dengan if statement.
try { // ... } catch (error) { if (error instanceof SyntaxError) { console.log(`JSON Error: ${error.message}`); } else if (error instanceof ReferenceError) { console.log(error.message); } else { console.log(error.stack); } }
Dengan operator instanceOf, kita bisa mendapatkan tipe dari eror yang terjadi. Dari sana kita bisa membuat percabangan bagaimana cara menangani erornya.
Custom Error
Setelah menangani eror, pada materi ini kita akan mempelajari bagaimana membuat eror sendiri. Ketika mengembangkan suatu aplikasi, akan ada banyak sekali kemungkinan munculnya eror. Seringkali, kita membutuhkan kelas eror sendiri untuk menunjukkan kesalahan yang spesifik dan tidak tersedia dalam kelas Error bawaan dari JavaScript.
Mari lihat lagi kode kita sebelumnya.
let json = '{ "age": 30 }'; try { let user = JSON.parse(json); if (!user.name) { throw new SyntaxError("'name' is required."); } console.log(user.name); console.log(user.age); } catch (error) { if (error instanceof SyntaxError) { console.log(`JSON Error: ${error.message}`); } else if (error instanceof ReferenceError) { console.log(error.message); } else { console.log(error.stack); } }
Awalnya, JSON.parse akan mengonversi data String menjadi object. Apabila format String tidak sesuai, maka fungsi tersebut akan melemparkan SyntaxError. Meskipun format atau sintaksis dari json string sudah sesuai, tetap ada kemungkinan data di dalamnya tidak lengkap. Saat ini kita masih menggunakan SyntaxError untuk menandai eror akibat data yang tidak lengkap, padahal secara sintaksis tidak ada masalah dari variabel json. Tentunya akan lebih baik jika kita punya Error yang lebih spesifik, bukan?
Untuk itu kita bisa membuat kelas Error kita sendiri dengan nama dan pesan yang lebih sesuai. Kelas ini merupakan turunan dari kelas Error yang sudah ada. Sebagai contoh, untuk mengecek validasi data dari json, kita bisa membuat kelas Error seperti ini:
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } }
Kelas ValidationError memiliki parameter constructor berupa message yang berisi pesan detail terkait erornya. Mari kita lihat penerapannya pada kode sebelumnya.
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } } let json = '{ "age": 30 }'; try { let user = JSON.parse(json); if (!user.name) { throw new ValidationError("'name' is required."); } if (!user.age) { throw new ValidationError("'age' is required."); } console.log(user.name); console.log(user.age); } catch (error) { if (error instanceof SyntaxError) { console.log(`JSON Syntax Error: ${error.message}`); } else if (error instanceof ValidationError) { console.log(`Invalid data: ${error.message}`); } else if (error instanceof ReferenceError) { console.log(error.message); } else { console.log(error.stack); } } /* output Invalid data: 'name' is required. */
Sekarang kode untuk menangani error menjadi lebih baik bukan? Penggunaan instanceOf akan memberikan hasil eror yang lebih detail dan sesuai dengan eror yang terjadi.
Sebelumnya : Modul Node JS | Selanjutnya : Concurrency |
0 Komentar