Panduan penanganan kesalahan JavaScript

Kesalahan itu baik. Penulis bahan, terjemahan yang kami terbitkan hari ini, mengatakan bahwa ia yakin bahwa ide ini diketahui semua orang. Sepintas, kesalahannya tampak menyeramkan. Mereka mungkin disertai dengan semacam kerugian. Kesalahan yang dibuat di depan umum merusak otoritas orang yang membuatnya. Tetapi membuat kesalahan, kita belajar dari mereka, yang berarti bahwa lain kali kita masuk ke dalam situasi di mana kita sebelumnya berperilaku salah, kita melakukan segala yang diperlukan.



Di atas kami berbicara tentang kesalahan yang dilakukan orang dalam kehidupan sehari-hari. Kesalahan dalam pemrograman adalah hal lain. Pesan kesalahan membantu kami meningkatkan kode, mereka memungkinkan kami untuk memberi tahu pengguna tentang proyek kami bahwa ada kesalahan, dan mungkin memberi tahu pengguna bagaimana berperilaku sehingga kesalahan tidak lagi terjadi.

Materi penanganan kesalahan JavaScript ini dibagi menjadi tiga bagian. Pertama, kami akan memberikan gambaran umum tentang sistem penanganan kesalahan dalam JavaScript dan berbicara tentang objek kesalahan. Setelah itu, kami mencari jawaban untuk pertanyaan apa yang harus dilakukan dengan kesalahan yang terjadi pada kode server (khususnya, ketika menggunakan bundel Node.js + Express.js). Selanjutnya, kita membahas penanganan kesalahan di React.js. Kerangka kerja yang akan dipertimbangkan di sini dipilih karena popularitasnya yang sangat besar. Namun, prinsip-prinsip untuk mengatasi kesalahan yang dibahas di sini bersifat universal, jadi meskipun Anda tidak menggunakan Express dan React, Anda dapat dengan mudah menerapkan apa yang Anda pelajari ke alat yang Anda gunakan.

Kode untuk proyek demo yang digunakan dalam materi ini dapat ditemukan di repositori ini .

1. Kesalahan dalam JavaScript dan cara universal untuk bekerja dengannya


Jika ada yang salah dalam kode Anda, Anda dapat menggunakan konstruksi berikut.

throw new Error('something went wrong') 

Selama eksekusi perintah ini, sebuah instance dari objek Error akan dibuat dan pengecualian akan dihasilkan (atau, seperti yang mereka katakan, "dilempar") dengan objek ini. Pernyataan melempar dapat melempar pengecualian yang mengandung ekspresi sewenang-wenang. Dalam hal ini, eksekusi skrip akan berhenti jika langkah-langkah belum diambil untuk menangani kesalahan.

Pemrogram JS pemula biasanya tidak menggunakan pernyataan throw . Mereka biasanya menemukan pengecualian yang dilempar oleh runtime bahasa atau pustaka pihak ketiga. Ketika ini terjadi, sesuatu seperti ReferenceError: fs is not defined masuk ke konsol ReferenceError: fs is not defined dan eksekusi program berhenti.

▍Object Error


Instance dari objek Error memiliki beberapa properti yang bisa kita gunakan. Properti pertama yang kami minati adalah message . Di sinilah garis mendapatkan yang dapat diteruskan ke konstruktor kesalahan sebagai argumen. Sebagai contoh, berikut ini menunjukkan bagaimana instantiate objek Error dan output ke konsol string yang dilewatkan oleh konstruktor dengan mengakses properti message .

 const myError = new Error('please improve your code') console.log(myError.message) // please improve your code 

Properti kedua dari objek, sangat penting, adalah jejak tumpukan kesalahan. Ini adalah properti stack . Beralih ke sana, Anda dapat melihat tumpukan panggilan (riwayat kesalahan), yang menunjukkan urutan operasi yang menyebabkan program tidak berfungsi. Secara khusus, ini memungkinkan kita untuk memahami file mana yang berisi kode buruk dan melihat urutan panggilan fungsi yang menyebabkan kesalahan. Ini adalah contoh dari apa yang dapat Anda lihat dengan mengakses properti stack .

 Error: please improve your code at Object.<anonymous> (/Users/gisderdube/Documents/_projects/hacking.nosync/error-handling/src/general.js:1:79) at Module._compile (internal/modules/cjs/loader.js:689:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10) at Module.load (internal/modules/cjs/loader.js:599:32) at tryModuleLoad (internal/modules/cjs/loader.js:538:12) at Function.Module._load (internal/modules/cjs/loader.js:530:3) at Function.Module.runMain (internal/modules/cjs/loader.js:742:12) at startup (internal/bootstrap/node.js:266:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3) 

Di sini, di bagian atas, ada pesan kesalahan, diikuti oleh indikasi bagian kode yang pelaksanaannya menyebabkan kesalahan, kemudian menjelaskan tempat dari mana bagian gagal ini dipanggil. Ini berlanjut ke "terjauh" dalam kaitannya dengan fragmen kode kesalahan.

▍ Penanganan generasi dan kesalahan


Membuat turunan dari objek Error , yaitu, mengeksekusi perintah dari bentuk new Error() , tidak menyebabkan konsekuensi khusus. Hal-hal menarik mulai terjadi setelah menerapkan operator throw , yang menghasilkan kesalahan. Seperti yang telah disebutkan, jika kesalahan tersebut tidak diproses, eksekusi skrip akan berhenti. Dalam hal ini, tidak ada bedanya apakah operator throw itu digunakan oleh programmer sendiri, apakah kesalahan terjadi di perpustakaan tertentu atau dalam runtime bahasa (di browser atau di Node.js). Mari kita bicara tentang berbagai skenario penanganan kesalahan.

▍bangun coba ... tangkap


try...catch adalah cara termudah untuk menangani kesalahan yang sering dilupakan. Namun, saat ini, digunakan jauh lebih intensif daripada sebelumnya, karena fakta bahwa itu dapat digunakan untuk menangani kesalahan dalam async/await konstruksi.

Blok ini dapat digunakan untuk menangani kesalahan yang terjadi dalam kode sinkron. Pertimbangkan sebuah contoh.

 const a = 5 try {   console.log(b) //  b   -   } catch (err) {   console.error(err) //          } console.log(a) //    ,    

Jika dalam contoh ini kami tidak menyertakan perintah console.log(b) gagal dalam try...catch , skrip akan dihentikan.

▍ akhirnya diblokir


Kadang-kadang terjadi bahwa beberapa kode perlu dieksekusi terlepas dari apakah kesalahan terjadi atau tidak. Untuk melakukan ini, Anda dapat menggunakan blok ketiga, opsional, finally di try...catch construct. Seringkali penggunaannya setara dengan beberapa kode yang datang segera setelah try...catch , tetapi dalam beberapa situasi dapat berguna. Berikut ini adalah contoh penggunaannya.

 const a = 5 try {   console.log(b) //  b   -   } catch (err) {   console.error(err) //          } finally {   console.log(a) //        } 

▍ Mekanisme tidak sinkron - panggilan balik


Saat memprogram dalam JavaScript, Anda harus selalu memperhatikan bagian kode yang berjalan secara tidak sinkron. Jika Anda memiliki fungsi asinkron dan ada kesalahan di dalamnya, skrip akan terus berjalan. Ketika mekanisme asinkron di JS diimplementasikan menggunakan panggilan balik (omong-omong, ini tidak dianjurkan), panggilan balik yang sesuai (fungsi panggilan balik) biasanya menerima dua parameter. Ini adalah sesuatu seperti parameter err , yang mungkin mengandung kesalahan, dan result - dengan hasil operasi asinkron. Itu terlihat seperti ini:

 myAsyncFunc(someInput, (err, result) => {   if(err) return console.error(err) //           console.log(result) }) 

Jika terjadi kesalahan dalam panggilan balik, itu terlihat di sana sebagai parameter err . Jika tidak, parameter ini akan mendapatkan nilai undefined atau null . Jika ternyata err sesuatu, penting untuk merespons ini karena dalam contoh kita, menggunakan perintah return , atau menggunakan if...else dan menempatkan perintah di blok else untuk bekerja dengan hasil operasi asinkron. Intinya adalah, jika terjadi kesalahan, mengecualikan kemungkinan bekerja dengan hasil, parameter result , yang dalam hal ini mungkin tidak undefined . Bekerja dengan nilai ini, jika diasumsikan, misalnya, bahwa itu berisi objek, itu sendiri dapat menyebabkan kesalahan. Katakanlah ini terjadi ketika Anda mencoba menggunakan result.data atau result.data mirip dengannya.

Mechanisms Mekanisme tidak sinkron - janji


Untuk melakukan operasi asinkron dalam JavaScript, lebih baik menggunakan janji daripada panggilan balik. Di sini, selain meningkatkan keterbacaan kode, ada mekanisme penanganan kesalahan yang lebih maju. Yaitu, Anda tidak perlu repot dengan objek kesalahan yang mungkin jatuh ke fungsi panggilan balik saat menggunakan janji. Di sini untuk tujuan ini disediakan blok catch khusus. Itu mencegat semua kesalahan yang terjadi dalam janji-janji yang ada sebelumnya, atau semua kesalahan yang terjadi dalam kode setelah catch sebelumnya. Harap perhatikan bahwa jika terjadi kesalahan dalam janji yang tidak memiliki blok catch untuk diproses, ini tidak akan menghentikan skrip dari mengeksekusi, tetapi pesan kesalahan tidak akan dapat dibaca secara khusus.

 (node:7741) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: something went wrong (node:7741) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. */ 

Akibatnya, Anda selalu dapat merekomendasikan, saat bekerja dengan janji, untuk menggunakan catch . Lihatlah sebuah contoh.

 Promise.resolve(1)   .then(res => {       console.log(res) // 1       throw new Error('something went wrong')       return Promise.resolve(2)   })   .then(res => {       console.log(res) //        })   .catch(err => {       console.error(err) //  ,     ,         return Promise.resolve(3)   })   .then(res => {       console.log(res) // 3   })   .catch(err => {       //      ,      -        console.error(err)   }) 

▍ Mekanisme tidak sinkron dan coba ... tangkap


Setelah konstruk async/await muncul di JavaScript, kami kembali ke cara klasik menangani kesalahan - untuk try...catch...finally . Menangani kesalahan dengan pendekatan ini sangat mudah dan nyaman. Pertimbangkan sebuah contoh.

 ;(async function() {   try {       await someFuncThatThrowsAnError()   } catch (err) {       console.error(err) //       }   console.log('Easy!') //   })() 

Dengan pendekatan ini, kesalahan dalam kode asinkron ditangani dengan cara yang sama seperti di sinkron. Akibatnya, sekarang, jika perlu, dalam satu catch Anda dapat menangani berbagai kesalahan yang lebih luas.

2. Menghasilkan dan memproses kesalahan dalam kode server


Sekarang kita memiliki alat untuk mengatasi kesalahan, mari kita lihat apa yang bisa kita lakukan dengan mereka dalam situasi nyata. Menghasilkan dan menangani kesalahan dengan benar adalah aspek penting dari pemrograman sisi server. Ada beberapa pendekatan untuk mengatasi kesalahan. Di sini kita akan mendemonstrasikan pendekatan menggunakan konstruktor kita sendiri untuk contoh objek Error dan kode kesalahan yang mudah diteruskan ke front-end atau mekanisme apa pun yang menggunakan API server. Bagaimana backend dari proyek tertentu terstruktur tidak terlalu penting, karena dengan pendekatan apa pun Anda dapat menggunakan ide yang sama tentang bekerja dengan kesalahan.

Sebagai kerangka kerja server yang bertanggung jawab untuk perutean, kami akan menggunakan Express.js. Mari kita pikirkan struktur apa yang kita butuhkan untuk mengatur sistem penanganan kesalahan yang efektif. Jadi inilah yang kami butuhkan:

  1. Penanganan kesalahan universal adalah beberapa mekanisme dasar yang cocok untuk menangani kesalahan, di mana pesan seperti Something went wrong, please try again or contact us , meminta pengguna untuk mencoba melakukan operasi yang gagal, lagi atau menghubungi pemilik server. Sistem ini tidak terlalu cerdas, tetapi setidaknya ia dapat memberi tahu pengguna bahwa ada kesalahan. Pesan semacam itu jauh lebih baik daripada "unduhan tanpa akhir" atau yang serupa.
  2. Memproses kesalahan khusus - mekanisme yang memungkinkan Anda untuk memberi tahu pengguna informasi terperinci tentang penyebab perilaku sistem yang tidak tepat dan memberinya saran khusus tentang cara menangani masalah tersebut. Misalnya, ini mungkin berhubungan dengan tidak adanya beberapa data penting dalam permintaan yang dikirim pengguna ke server, atau bahwa sudah ada catatan tertentu dalam database yang ia coba tambahkan lagi, dan seterusnya.

▍ Mengembangkan konstruktor sendiri objek kesalahan


Di sini kita akan menggunakan kelas Error standar dan memperluasnya. Menggunakan mekanisme pewarisan dalam JavaScript berisiko, tetapi dalam kasus ini, mekanisme ini sangat berguna. Mengapa kita membutuhkan warisan? Faktanya adalah agar kita dapat dengan mudah men-debug kode, kita memerlukan informasi tentang jejak tumpukan kesalahan. Memperluas kelas Error standar, kami mendapatkan kemampuan untuk melacak tumpukan tanpa usaha ekstra. Kami menambahkan dua properti ke objek kesalahan kami sendiri. Yang pertama adalah properti code , yang dapat diakses menggunakan struktur form err.code . Yang kedua adalah properti status . Ini akan merekam kode status HTTP, yang rencananya akan dikirim ke bagian klien dari aplikasi.

Inilah yang tampak seperti kelas CustomError , yang kodenya dirancang sebagai modul.

 class CustomError extends Error {   constructor(code = 'GENERIC', status = 500, ...params) {       super(...params)       if (Error.captureStackTrace) {           Error.captureStackTrace(this, CustomError)       }       this.code = code       this.status = status   } } module.exports = CustomError 

▍ Routing


Sekarang objek kesalahan kita siap digunakan, kita perlu mengkonfigurasi struktur rute. Seperti disebutkan di atas, kita perlu menerapkan pendekatan terpadu untuk penanganan kesalahan, yang memungkinkan kita menangani kesalahan secara sama untuk semua rute. Secara default, kerangka kerja Express.js tidak sepenuhnya mendukung skema semacam itu. Faktanya adalah bahwa semua rutenya dienkapsulasi.

Untuk mengatasi masalah ini, kita dapat mengimplementasikan pengendali rute kita sendiri dan mendefinisikan logika rute dalam bentuk fungsi biasa. Berkat pendekatan ini, jika fungsi rute (atau fungsi lainnya) melempar kesalahan, itu akan jatuh ke pengendali rute, yang kemudian dapat meneruskannya ke bagian klien dari aplikasi. Jika terjadi kesalahan pada server, kami berencana untuk mentransfernya ke front-end dalam format berikut, dengan asumsi bahwa JSON-API akan digunakan untuk ini:

 {   error: 'SOME_ERROR_CODE',   description: 'Something bad happened. Please try again or contact support.' } 

Jika pada tahap ini apa yang terjadi tampaknya tidak dapat dipahami oleh Anda - jangan khawatir - teruslah membaca, cobalah bekerja dengan apa yang sedang dibahas, dan secara bertahap Anda akan mengetahuinya. Bahkan, jika kita berbicara tentang pelatihan komputer, pendekatan "top-down" digunakan di sini, ketika ide-ide umum pertama kali dibahas dan kemudian transisi ke rincian dilakukan.

Seperti inilah kode penanganan rute.

 const express = require('express') const router = express.Router() const CustomError = require('../CustomError') router.use(async (req, res) => {   try {       const route = require(`.${req.path}`)[req.method]       try {           const result = route(req) //    route           res.send(result) //   ,     route       } catch (err) {           /*                ,    route             */           if (err instanceof CustomError) {               /*                   -                                  */               return res.status(err.status).send({                   error: err.code,                   description: err.message,               })           } else {               console.error(err) //                  //   -                   return res.status(500).send({                   error: 'GENERIC',                   description: 'Something went wrong. Please try again or contact support.',               })           }       }   } catch (err) {       /*          ,    ,  ,            ,  ,          ,                       */       res.status(404).send({           error: 'NOT_FOUND',           description: 'The resource you tried to access does not exist.',       })   } }) module.exports = router 

Kami percaya komentar dalam kode menjelaskannya dengan baik. Kami berharap bahwa membacanya lebih nyaman daripada penjelasan kode yang diberikan setelahnya.

Sekarang lihat file rute.

 const CustomError = require('../CustomError') const GET = req => {   //       return { name: 'Rio de Janeiro' } } const POST = req => {   //       throw new Error('Some unexpected error, may also be thrown by a library or the runtime.') } const DELETE = req => {   //  ,      throw new CustomError('CITY_NOT_FOUND', 404, 'The city you are trying to delete could not be found.') } const PATCH = req => {   //      CustomError   try {       //   -        throw new Error('Some internal error')   } catch (err) {       console.error(err) //    ,           throw new CustomError(           'CITY_NOT_EDITABLE',           400,           'The city you are trying to edit is not editable.'       )   } } module.exports = {   GET,   POST,   DELETE,   PATCH, } 

Dalam contoh ini, tidak ada yang dilakukan dengan kueri itu sendiri. Ini hanya mempertimbangkan berbagai skenario untuk terjadinya kesalahan. Jadi, misalnya, permintaan GET /city akan jatuh ke fungsi const GET = req =>... , permintaan POST /city akan jatuh ke fungsi const POST = req =>... dan seterusnya. Skema ini juga berfungsi saat menggunakan parameter kueri. Misalnya, untuk permintaan formulir GET /city?startsWith=R Secara umum, telah ditunjukkan di sini bahwa saat memproses kesalahan, frontend bisa mendapatkan kesalahan umum yang hanya berisi penawaran untuk mencoba lagi atau menghubungi pemilik server, atau kesalahan yang dihasilkan menggunakan konstruktor CustomError yang berisi informasi terperinci tentang masalah tersebut.
Data kesalahan umum akan datang ke bagian klien dari aplikasi dalam bentuk berikut:

 {   error: 'GENERIC',   description: 'Something went wrong. Please try again or contact support.' } 

Konstruktor CustomError digunakan seperti ini:

 throw new CustomError('MY_CODE', 400, 'Error description') 

Ini memberikan kode JSON berikut yang diteruskan ke frontend:

 {   error: 'MY_CODE',   description: 'Error description' } 

Sekarang kita telah benar-benar bekerja pada bagian server dari aplikasi, log kesalahan yang tidak berguna tidak lagi jatuh ke dalam bagian klien. Sebagai gantinya, klien menerima informasi berguna tentang apa yang salah.

Jangan lupa bahwa di sinilah letak repositori dengan kode yang dipertimbangkan di sini. Anda dapat mengunduhnya, bereksperimen dengannya, dan, jika perlu, menyesuaikannya dengan kebutuhan proyek Anda.

3. Bekerja dengan kesalahan pada klien


Sekarang saatnya untuk menggambarkan bagian ketiga dari sistem penanganan kesalahan front-end kami. Di sini perlu, pertama, untuk menangani kesalahan yang terjadi di bagian klien dari aplikasi, dan kedua, perlu untuk memberi tahu pengguna tentang kesalahan yang terjadi di server. Kami pertama-tama akan berurusan dengan menampilkan informasi kesalahan server. Seperti yang telah disebutkan, perpustakaan Bereaksi akan digunakan dalam contoh ini.

▍ Simpan informasi kesalahan dalam keadaan aplikasi


Seperti data lainnya, kesalahan dan pesan kesalahan dapat berubah, jadi masuk akal untuk menempatkannya dalam keadaan komponen. Ketika komponen dipasang, data kesalahan diatur ulang, oleh karena itu, ketika pengguna pertama kali melihat halaman, tidak akan ada pesan kesalahan.

Hal berikutnya yang harus diatasi adalah bahwa kesalahan dengan tipe yang sama perlu ditunjukkan dengan gaya yang sama. Dengan analogi dengan server, di sini Anda dapat membedakan 3 jenis kesalahan.

  1. Kesalahan global - kategori ini mencakup pesan kesalahan yang bersifat umum yang berasal dari server, atau kesalahan yang, misalnya, terjadi jika pengguna tidak masuk ke sistem dalam situasi serupa lainnya.
  2. Kesalahan spesifik yang dihasilkan oleh sisi server dari aplikasi - ini termasuk kesalahan yang dilaporkan dari server. Misalnya, kesalahan serupa terjadi jika pengguna mencoba masuk dan mengirim nama pengguna dan kata sandi ke server, dan server memberi tahu dia bahwa kata sandi itu salah. Hal-hal seperti itu tidak dicentang di bagian klien dari aplikasi, jadi pesan tentang kesalahan seperti itu harus datang dari server.
  3. Kesalahan spesifik yang dihasilkan oleh bagian klien dari aplikasi. Contoh kesalahan tersebut adalah pesan tentang alamat email yang tidak valid yang dimasukkan di bidang yang sesuai.

Kesalahan tipe kedua dan ketiga sangat mirip, Anda dapat bekerja dengannya menggunakan state store komponen dari level yang sama. Perbedaan utama mereka adalah bahwa mereka berasal dari sumber yang berbeda. Di bawah ini, menganalisis kode, kita akan melihat bekerja dengan mereka.

Ini akan menggunakan sistem bawaan untuk mengelola keadaan aplikasi di Bereaksi, tetapi, jika perlu, Anda dapat menggunakan solusi khusus untuk mengelola negara - seperti MobX atau Redux.

▍ Kesalahan global


Biasanya, pesan kesalahan tersebut disimpan di komponen tingkat tertinggi dengan status. Mereka ditampilkan dalam elemen antarmuka pengguna statis. Ini bisa berupa kotak merah di bagian atas layar, jendela modal, atau apa pun. Implementasinya tergantung pada proyek spesifik. Seperti inilah tampilan pesan kesalahan.


Pesan kesalahan global

Sekarang lihat kode yang disimpan dalam file Application.js .

 import React, { Component } from 'react' import GlobalError from './GlobalError' class Application extends Component {   constructor(props) {       super(props)       this.state = {           error: '',       }       this._resetError = this._resetError.bind(this)       this._setError = this._setError.bind(this)   }   render() {       return (           <div className="container">               <GlobalError error={this.state.error} resetError={this._resetError} />               <h1>Handling Errors</h1>           </div>       )   }   _resetError() {       this.setState({ error: '' })   }   _setError(newError) {       this.setState({ error: newError })   } } export default Application 

, , Application.js , . , .

GlobalError , x , . GlobalError ( GlobalError.js ).

 import React, { Component } from 'react' class GlobalError extends Component {   render() {       if (!this.props.error) return null       return (           <div               style={{                   position: 'fixed',                   top: 0,                   left: '50%',                   transform: 'translateX(-50%)',                   padding: 10,                   backgroundColor: '#ffcccc',                   boxShadow: '0 3px 25px -10px rgba(0,0,0,0.5)',                   display: 'flex',                   alignItems: 'center',               }}           >               {this.props.error}                              <i                   className="material-icons"                   style={{ cursor: 'pointer' }}                   onClick={this.props.resetError}               >                   close               </font></i>           </div>       )   } } export default GlobalError 

if (!this.props.error) return null . , . . , , , . , , x , - , .

, , _setError Application.js . , , , , ( error: 'GENERIC' ). ( GenericErrorReq.js ).

 import React, { Component } from 'react' import axios from 'axios' class GenericErrorReq extends Component {   constructor(props) {       super(props)       this._callBackend = this._callBackend.bind(this)   }   render() {       return (           <div>               <button onClick={this._callBackend}>Click me to call the backend</button>           </div>       )   }   _callBackend() {       axios           .post('/api/city')           .then(result => {               //  -     ,               })           .catch(err => {               if (err.response.data.error === 'GENERIC') {                   this.props.setError(err.response.data.description)               }           })   } } export default GenericErrorReq 

, . , , . . -, , -, UX-, , — .

▍ ,


, , , .




, . . . SpecificErrorReq.js .

 import React, { Component } from 'react' import axios from 'axios' import InlineError from './InlineError' class SpecificErrorRequest extends Component {   constructor(props) {       super(props)       this.state = {           error: '',       }       this._callBackend = this._callBackend.bind(this)   }   render() {       return (           <div>               <button onClick={this._callBackend}>Delete your city</button>               <InlineError error={this.state.error} />           </div>       )   }   _callBackend() {       this.setState({           error: '',       })       axios           .delete('/api/city')           .then(result => {               //  -     ,               })           .catch(err => {               if (err.response.data.error === 'GENERIC') {                   this.props.setError(err.response.data.description)               } else {                   this.setState({                       error: err.response.data.description,                   })               }           })   } } export default SpecificErrorRequest 

, , , x . , , . , , — , , , . , , . , , , — .

▍,


, , , . , , - . .


,

SpecificErrorFrontend.js , .

 import React, { Component } from 'react' import axios from 'axios' import InlineError from './InlineError' class SpecificErrorRequest extends Component {   constructor(props) {       super(props)       this.state = {           error: '',           city: '',       }       this._callBackend = this._callBackend.bind(this)       this._changeCity = this._changeCity.bind(this)   }   render() {       return (           <div>               <input                   type="text"                   value={this.state.city}                   style={{ marginRight: 15 }}                   onChange={this._changeCity}               />               <button onClick={this._callBackend}>Delete your city</button>               <InlineError error={this.state.error} />           </div>       )   }   _changeCity(e) {       this.setState({           error: '',           city: e.target.value,       })   }   _validate() {       if (!this.state.city.length) throw new Error('Please provide a city name.')   }   _callBackend() {       this.setState({           error: '',       })       try {           this._validate()       } catch (err) {           return this.setState({ error: err.message })       }       axios           .delete('/api/city')           .then(result => {               //  -     ,               })           .catch(err => {               if (err.response.data.error === 'GENERIC') {                   this.props.setError(err.response.data.description)               } else {                   this.setState({                       error: err.response.data.description,                   })               }           })   } } export default SpecificErrorRequest 


, , ( GENERIC ), , . , , , , , , , , . .

Ringkasan


Kami harap Anda sekarang memiliki pemahaman tentang cara menangani kesalahan dalam aplikasi web. Sesuatu seperti ini console.error(err)harus digunakan hanya untuk keperluan debugging, hal-hal seperti itu dilupakan oleh programmer tidak boleh menembus ke produksi. Menyederhanakan solusi untuk masalah pencatatan menggunakan beberapa perpustakaan yang sesuai seperti loglevel .

Pembaca yang budiman! Bagaimana Anda menangani kesalahan dalam proyek Anda?

Source: https://habr.com/ru/post/id431078/


All Articles