Terlepas dari tingkat keterampilan Anda, kesalahan atau pengecualian adalah bagian dari kehidupan pengembang aplikasi Anda. Ketidakkonsistenan pengembangan web menyisakan banyak tempat di mana kesalahan dapat dan memang telah terjadi. Kunci solusinya adalah menangani kesalahan yang tidak terduga (atau yang dapat diperkirakan) untuk mengontrol pengalaman pengguna. Dengan JavaScript, ada berbagai fitur teknis dan bahasa yang dapat digunakan untuk menyelesaikan masalah apa pun dengan benar.
Berbahaya untuk menangani kesalahan dalam JavaScript. Jika Anda percaya pada hukum Murphy, apa yang salah pada akhirnya akan salah! Dalam artikel ini, saya akan menggali penanganan kesalahan di JavaScript. Saya akan melibatkan beberapa jebakan dan praktik yang baik. Akhirnya, kita akan membahas pemrosesan kode asinkron dan Ajax.
Saya pikir model JavaScript yang digerakkan oleh acara menambah makna bahasa ini. Saya pikir tidak ada perbedaan antara mesin yang digerakkan oleh peristiwa dan mekanisme pelaporan kesalahan dari browser semacam ini. Setiap kali terjadi kesalahan, itu setara dengan melempar suatu peristiwa pada titik waktu tertentu. Secara teori, kita dapat menangani peristiwa melempar kesalahan di JavaScript seperti kita menangani peristiwa biasa. Jika ini terdengar aneh bagi Anda, fokuslah untuk memulai perjalanan di bawah ini. Artikel ini hanya menargetkan JavaScript klien.
Contoh
Contoh kode yang digunakan dalam artikel ini dapat diperoleh di GitHub. Halaman saat ini terlihat seperti ini:
Mengklik setiap tombol akan melempar kesalahan. Ini mensimulasikan pengecualian tipe typeError. Berikut ini adalah definisi dan unit uji modul tersebut.
function error () {var foo = {}; kembalikan foo.bar ();}Pertama, fungsi ini mendefinisikan objek kosong FOO. Perhatikan bahwa metode bar () tidak didefinisikan di mana pun. Kami menggunakan tes unit untuk memverifikasi bahwa ini memang melakukan kesalahan.
itu ('melempar typeError', function () {harus.throws (target, typeError);});Uji unit ini menggunakan pernyataan uji dari pustaka mocha dan harus.js. Mocha adalah kerangka kerja tes yang berjalan, dan harus.js adalah perpustakaan pernyataan. Jika Anda tidak terlalu terbiasa dengan mereka, Anda dapat menelusuri dokumen mereka secara online secara gratis. Kasing uji biasanya dimulai dengan itu ('deskripsi') dan diakhiri dengan passing atau kegagalan pernyataan yang seharusnya. Keuntungan menggunakan kerangka kerja ini adalah bahwa ia dapat diuji unit dalam simpul, bukan di browser. Saya sarankan Anda melakukan tes ini dengan serius karena mereka memvalidasi banyak konsep dasar utama dalam JavaScript.
Seperti yang ditunjukkan di atas, kesalahan () mendefinisikan objek kosong dan kemudian mencoba memanggil metode di dalamnya. Karena metode bar () tidak ada dalam objek ini, itu akan melempar pengecualian. Percayalah, dalam bahasa dinamis seperti JavaScript, siapa pun dapat membuat kesalahan seperti itu.
Demonstrasi yang buruk
Mari kita lihat metode penanganan kesalahan yang buruk. Saya akan mengabstraksi tindakan yang salah dan mengikatnya ke tombol. Inilah tes unit penangan rasanya:
fungsi badhandler (fn) {coba {return fn (); } catch (e) {} return null;}Fungsi pemrosesan ini menerima fungsi panggilan balik FN sebagai ketergantungan. Kemudian fungsi dipanggil di dalam pawang. Contoh tes unit ini cara menggunakan metode ini.
itu ('Mengembalikan nilai tanpa kesalahan', function () {var fn = function () {return 1;}; var result = target (fn); hasilnya. harus (hasil) .Equal (null);});Seperti yang Anda lihat, jika terjadi kesalahan, cara penanganan yang aneh ini mengembalikan nol. Fungsi panggilan balik ini FN () akan menunjuk ke metode atau kesalahan hukum. Acara pemrosesan klik di bawah ini melengkapi sisanya.
(function (handler, bom) {var badbutton = document.geteLementById ('bad'); if (badbutton) {badbutton.addeventlistener ('klik', function () {handler (bom); console.log ('bayangkan, dipromosikan untuk kesalahan persembunyian');});}}}}}}};Yang buruk adalah bahwa yang baru saja saya dapatkan adalah nol. Ini membuat saya sangat bingung ketika saya berpikir untuk menentukan apa yang salah. Strategi keheningan ini ketika kesalahan terjadi mencakup setiap tautan dari desain pengalaman pengguna hingga korupsi data. Sisi frustasi diikuti adalah bahwa saya harus menghabiskan berjam-jam debugging tetapi tidak bisa melihat kesalahan di blok kode coba-tangkapan. Pemrosesan yang aneh ini menyembunyikan semua kesalahan dalam kode, dan mengasumsikan bahwa semuanya normal. Ini dapat dieksekusi dengan lancar di beberapa tim yang tidak memperhatikan kualitas kode. Namun, kesalahan tersembunyi ini pada akhirnya akan memaksa Anda untuk menghabiskan berjam -jam men -debug kode Anda. Dalam solusi multi-layer yang bergantung pada tumpukan panggilan, dimungkinkan untuk menentukan dari mana kesalahan berasal. Mungkin tepat untuk menangani penangkapan mencoba secara diam-diam dalam kasus yang jarang terjadi. Tetapi jika Anda mengalami kesalahan, Anda akan menghadapinya, yang bukan solusi yang baik.
Kegagalan ini adalah strategi keheningan akan mendorong Anda untuk menangani kesalahan dalam kode Anda dengan lebih baik. JavaScript menyediakan cara yang lebih elegan untuk menangani masalah jenis ini.
Bukan solusi yang dapat dibaca
Mari kita lanjutkan, mari kita lihat pendekatan yang sulit dipahami. Saya akan melewatkan bagian yang dipasangkan erat dengan DOM. Bagian ini tidak berbeda dari pendekatan buruk yang baru saja kita lihat. Fokusnya adalah pada bagian uji unit di bawah ini yang menangani pengecualian.
function UglyHandler (fn) {coba {return fn (); } catch (e) {throw error ('kesalahan baru'); }} it ('Mengembalikan kesalahan baru dengan kesalahan', function () {var fn = function () {throw new typeError ('type error');}; harus.throws (function () {target (fn);}, error);});Ada peningkatan yang baik dibandingkan dengan pengobatan yang buruk sekarang. Pengecualian dilemparkan ke dalam tumpukan panggilan. Yang saya sukai adalah bahwa kesalahan dibebaskan dari tumpukan, yang sangat membantu untuk debugging. Ketika pengecualian dilemparkan, penerjemah akan melihat fungsi pemrosesan berikutnya pada tingkat di tumpukan panggilan. Ini memberikan banyak peluang untuk menangani kesalahan di tingkat atas tumpukan panggilan. Sayangnya, karena dia adalah kesalahan yang sulit, saya tidak dapat melihat informasi kesalahan asli. Jadi saya harus melihat di sepanjang tumpukan panggilan dan menemukan pengecualian paling primitif. Tapi setidaknya saya tahu ada kesalahan yang terjadi di mana pengecualian dilemparkan.
Meskipun penanganan kesalahan yang tidak dapat dibaca ini tidak berbahaya, itu membuat kode sulit dipahami. Mari kita lihat bagaimana browser menangani kesalahan.
Panggil tumpukan
Kemudian, salah satu cara untuk melempar pengecualian adalah dengan menambahkan ... Tangkap blok kode di tingkat atas tumpukan panggilan. Misalnya:
fungsi main (bom) {coba {bom (); } catch (e) {// menangani semua hal kesalahan}}Tapi, ingat saya mengatakan bahwa browser didorong oleh acara? Ya, pengecualian di JavaScript tidak lebih dari suatu acara. Penerjemah menghentikan program pada konteks di mana pengecualian saat ini terjadi dan melempar pengecualian. Untuk mengonfirmasi hal ini, berikut ini adalah fungsi penanganan acara global yang bisa kita lihat. Sepertinya ini:
window.addeventListener ('error', function (e) {var error = e.error; console.log (error);});Penangan acara ini menangkap kesalahan di lingkungan eksekusi. Peristiwa kesalahan akan menghasilkan berbagai kesalahan di berbagai tempat. Inti dari pendekatan ini adalah untuk menangani kesalahan secara terpusat dalam kode. Sama seperti acara lainnya, Anda dapat menggunakan pawang global untuk menangani berbagai kesalahan. Ini membuat kesalahan penanganan hanya satu tujuan jika Anda mematuhi prinsip-prinsip solid (tanggung jawab tunggal, tertutup terbuka, Liskov, pemisahan antarmuka dan inversi ketergantungan). Anda dapat mendaftarkan fungsi penanganan kesalahan kapan saja. Interpreter menjalankan loop fungsi -fungsi ini. Kode ini dibebaskan dari pernyataan yang diisi dengan cobalah ... tangkap dan menjadi mudah untuk debug. Kunci dari pendekatan ini adalah menangani kesalahan yang terjadi seperti peristiwa JavaScript normal.
Sekarang, ada cara untuk menampilkan tumpukan panggilan dengan fungsi pemrosesan global. Apa yang bisa kita lakukan dengannya? Bagaimanapun, kita harus menggunakan tumpukan panggilan.
Rekam tumpukan panggilan
Tumpukan panggilan sangat berguna dalam menangani perbaikan bug. Berita baiknya adalah bahwa browser memberikan informasi ini. Meskipun atribut tumpukan objek kesalahan tidak standar saat ini, atribut ini umumnya didukung di browser yang lebih baru.
Jadi, hal keren yang bisa kita lakukan adalah mencetaknya ke server:
window.addeventListener ('error', function (e) {var stack = e.error.stack; var message = e.error.toString (); if (stack) {pesan + = '/n' + stack;} var xhr = new xmlHtprequest (); xhr.open ('post', '(', '(', '(', '(', '(', ',', ',', ','/XMLHTPREQUEST ();Mungkin tidak jelas dalam contoh kode, tetapi pawang acara ini akan dipicu oleh kode kesalahan sebelumnya. Seperti disebutkan di atas, masing -masing pawang memiliki satu tujuan, yang membuat kode kering (jangan ulangi diri Anda tanpa berulang kali membuat roda). Yang saya minati adalah cara menangkap pesan -pesan ini di server.
Berikut adalah tangkapan layar dari runtime simpul:
Tumpukan panggilan sangat membantu untuk men -debug kode. Jangan pernah meremehkan peran tumpukan panggilan.
Pemrosesan asinkron
Oh, cukup berbahaya untuk menangani kode asinkron! JavaScript membawa kode asinkron dari lingkungan eksekusi saat ini. Ini berarti ada masalah dengan pernyataan mencoba ... tangkap di bawah ini.
function asynchandler (fn) {coba {setTimeout (function () {fn ();}, 1); } catch (e) {}}Masih ada bagian yang tersisa dari tes unit ini:
itu ('tidak menangkap pengecualian dengan kesalahan', function () {var fn = function () {throw new typeError ('type error');}; failurepromise (function () {target (fn);}). harus.be.rectedwith (typeError);}); function fRACTPROMISE (fn) {{{{{{{fnome) {function {function) {function {function) {function {function) (function);Saya harus mengakhiri penangan ini dengan janji untuk memverifikasi pengecualian. Perhatikan bahwa meskipun kode saya semuanya dalam coba ... tangkap, pengecualian yang tidak ditangani masih muncul. Ya, coba ... Tangkap hanya berfungsi di lingkungan eksekusi yang terpisah. Ketika pengecualian dilemparkan, lingkungan eksekusi interpreter tidak lagi menjadi blok TRY-Catch saat ini. Perilaku ini terjadi mirip dengan panggilan AJAX. Jadi, sekarang ada dua opsi. Alternatifnya adalah menangkap pengecualian dalam panggilan balik yang tidak sinkron:
setTimeout (function () {coba {fn ();} catch (e) {// menangani kesalahan async ini}}, 1);Meskipun metode ini berguna, masih ada banyak ruang untuk perbaikan. Pertama, coba ... Tangkap blok kode muncul di mana -mana dalam kode. Bahkan, dalam panggilan pemrograman tahun 1970 -an, mereka ingin kode mereka kembali. Selain itu, mesin V8 mencegah penggunaan blok Coba ... Tangkap Kode dalam Fungsi (V8 adalah mesin JavaScript yang digunakan oleh browser dan simpul Chrome). Mereka merekomendasikan menulis blok kode ini yang menangkap pengecualian di bagian atas tumpukan panggilan.
Jadi, apa yang dikatakan ini kepada kita? Seperti yang saya katakan di atas, penangan kesalahan global dalam konteks eksekusi apa pun diperlukan. Jika Anda menambahkan penangan kesalahan ke objek jendela, yaitu, Anda sudah selesai! Bukankah menyenangkan mengikuti prinsip -prinsip kering dan padat? Penangan kesalahan global akan membuat kode Anda dapat dibaca dan bersih.
Berikut ini adalah laporan yang dicetak pada penanganan pengecualian sisi server. Perhatikan bahwa jika Anda menggunakan kode dalam contoh, output dapat sedikit bervariasi tergantung pada browser yang Anda gunakan.
Penangan ini bahkan dapat memberi tahu saya kesalahan mana yang berasal dari kode asinkron. Ini memberitahu saya bahwa kesalahan itu berasal dari penangan setTimeout (). Keren abis!
Kesalahan adalah bagian dari setiap aplikasi, tetapi penanganan kesalahan yang tepat tidak. Setidaknya ada dua cara untuk mengatasi kesalahan. Salah satunya adalah solusi kegagalan, keheningan, yaitu, mengabaikan kesalahan dalam kode. Cara lain adalah dengan cepat mendeteksi dan menyelesaikan kesalahan, yaitu berhenti pada kesalahan dan mereproduksi. Saya pikir saya telah menyatakan dengan jelas apa yang saya sukai dan mengapa saya menyukainya. Pilihan saya: Jangan sembunyikan masalahnya. Tidak ada yang akan menyalahkan Anda atas acara yang tidak terduga dalam program Anda. Ini dapat diterima, untuk memecahkan poin, mereproduksi, dan mencoba pengguna. Di dunia yang tidak sempurna, penting untuk memberi diri Anda kesempatan. Kesalahan tidak bisa dihindari, dan apa yang Anda lakukan adalah penting untuk menyelesaikan kesalahan. Penggunaan fitur penanganan kesalahan JavaScript yang masuk akal dan decoding otomatis dan fleksibel dapat membuat pengalaman pengguna lebih lancar, dan juga membuat diagnosis pengembang bekerja lebih mudah.