Articles

tratarea erorilor, ” încercați..catch”

Posted by admin

Nu contează cât de mare suntem la programare, uneori scripturile noastre au erori. Acestea pot apărea din cauza greșelilor noastre, a unei intrări neașteptate a utilizatorului, a unui răspuns eronat al serverului și din alte o mie de motive.de obicei, un script „moare” (se oprește imediat) în cazul unei erori, imprimându-l în consolă.

dar există un construct de sintaxă try..catch care ne permite să” prindem ” erori, astfel încât scriptul să poată, în loc să moară, să facă ceva mai rezonabil.,

„try…catch” sintaxa

try..catch construirea a două blocuri principale: try, apoi catch:

try { // code...} catch (err) { // error handling}

Acesta funcționează ca aceasta:

  1. în Primul rând, codul în try {...} este executat.
  2. Daca nu au existat erori, atunci catch(err) este ignorat: executarea ajunge la sfârșitul try și merge mai departe, sărind peste catch.,
  3. dacă apare o eroare, atunci execuția try este oprită, iar controlul curge la începutul catch(err). Variabila err (putem folosi orice nume pentru aceasta) va conține un obiect de eroare cu detalii despre cele întâmplate.

Deci, o eroare în interiorul try {…} bloc nu-l omoare pe script – avem o șansă să-l ocupe în catch.,să ne uităm la câteva exemple.

try..catch funcționează numai pentru erori de rulare

Pentru try..catch la locul de muncă, codul trebuie să fie runnable. Cu alte cuvinte, ar trebui să fie JavaScript valid.

nu va funcționa în cazul în care codul este sintactic greșit, de exemplu, are de neegalat acolade:

try { {{{{{{{{{{{{} catch(e) { alert("The engine can't understand this code, it's invalid");}

motor JavaScript mai întâi citește codul, și apoi se ruleaza-l., Erorile care apar în faza de citire se numesc erori „parse-time” și sunt nerecuperabile (din interiorul acelui cod). Asta pentru că motorul nu poate înțelege codul.deci, try..catch poate gestiona numai Erorile care apar în codul valid. Astfel de erori se numesc „erori de rulare” sau, uneori, „excepții”.

obiect de eroare

când apare o eroare, JavaScript generează un obiect care conține detaliile despre el., Obiectul este apoi transmis ca argument catch:

try { // ...} catch(err) { // <-- the "error object", could use another word instead of err // ...}

Pentru toate built-in erori, eroarea obiect are două proprietăți principale:

nameEroare numele. De exemplu, pentru o variabilă nedefinită care este"ReferenceError".messagemesaj Textual despre detalii de eroare.

există și alte proprietăți non-standard disponibile în majoritatea mediilor., Unul dintre cele mai utilizate și acceptate este:

stackstiva de apeluri curente: un șir cu informații despre secvența apelurilor imbricate care au dus la eroare. Folosit în scopuri de depanare.

de exemplu:

opțional” captură ” obligatoriu

o adăugare recentă
aceasta este o adăugare recentă a limbii. Browserele vechi pot avea nevoie de polyfills.,

Dacă nu avem nevoie de detaliile de eroare, catch poate omite:

try { // ...} catch { // <-- without (err) // ...}

Utilizarea „try…catch”

Să exploreze viața reală caz de utilizare de try..catch.

după cum știm deja, JavaScript acceptă JSON.parse (str) metoda pentru a citi valorile codificate JSON.

De obicei este folosit pentru a decoda datele primite prin rețea, de la server sau de la o altă sursă.,

îl primim și apelăm JSON.parse astfel:

puteți găsi informații mai detaliate despre JSON în metodele JSON, capitolul toJSON.

dacă jsoneste malformat, JSON.parse generează o eroare, deci scriptul”moare”.ar trebui să fim mulțumiți de asta? Bineînțeles că nu!în acest fel, dacă ceva nu este în regulă cu datele, vizitatorul nu va ști niciodată acest lucru (cu excepția cazului în care deschide consola dezvoltatorului). Și oamenilor nu le place când ceva „moare” fără niciun mesaj de eroare.,

Să folosim try..catch să se ocupe de eroare:

Aici vom folosi catch bloc doar pentru a arăta mesajul, dar putem face mult mai mult: trimite o nouă cerere de rețea, vă propun o alternativă la un vizitator, trimite informații despre o eroare la un exploatarea instalației, … . E mult mai bine decât să mori.

Aruncarea propriile noastre erori

dacă json este sintactic corect, dar nu au un necesar name proprietate?,

let json = '{ "age": 30 }'; // incomplete datatry { let user = JSON.parse(json); // <-- no errors alert( user.name ); // no name!} catch (e) { alert( "doesn't execute" );}

Aici JSON.parse execută în mod normal, dar absența name este de fapt o eroare pentru noi.

pentru a unifica tratarea erorilor, vom folosi operatorul throw.

„arunca” operator

throw operatorul generează o eroare.

sintaxa este:

throw <error object>

tehnic, putem folosi orice ca obiect de eroare., Care ar putea fi chiar un primitiv, cum ar fi un număr sau un șir de caractere, dar este mai bine de a utiliza obiectele, de preferință cu name și message properties (să rămână oarecum compatibil cu built-in de erori).

JavaScript are multe built-in de constructori pentru erorile standard: Error, SyntaxError, ReferenceError, TypeError și altele. Le putem folosi și pentru a crea obiecte de eroare.,

sintaxa Lor este:

let error = new Error(message);// orlet error = new SyntaxError(message);let error = new ReferenceError(message);// ...

Pentru built-in de erori (nu pentru orice obiecte, doar pentru erori), name proprietatea este exact numele de constructor. Și message este luat din argument.,

De exemplu:

let error = new Error("Things happen o_O");alert(error.name); // Erroralert(error.message); // Things happen o_O

Să vedem ce fel de eroare JSON.parse generează:

try { JSON.parse("{ bad json o_O }");} catch(e) { alert(e.name); // SyntaxError alert(e.message); // Unexpected token b in JSON at position 2}

după Cum putem vedea, că e SyntaxError.

și în cazul nostru, absența name este eroarea, deoarece utilizatorii trebuie să aibă un name.,

Deci, haideți să-l arunce:

În linia (*), throw operator generează un SyntaxError cu message, la fel ca JavaScript-ar genera în sine. Executarea tryse oprește imediat și fluxul de control sare în catch.

catch a devenit un singur loc pentru eroare de manipulare: atât pentru JSON.parse și alte cazuri.,în exemplul de mai sus folosimtry..catchpentru a gestiona date incorecte. Dar este posibil să apară o altă eroare neașteptată în blocul try {...}? Ca o eroare de programare (variabila nu este definită) sau altceva, nu doar acest lucru „date incorecte”.

de exemplu:

desigur, totul este posibil! Programatorii fac greșeli. Chiar și în utilitățile open-source folosite de milioane de zeci de ani – dintr-o dată poate fi descoperită o eroare care duce la hack-uri teribile.,

În cazul nostru, try..catch este plasat pentru a prinde Erorile „date incorecte”. Dar, prin natura sa, catchprimește toate erorile de la try. Aici apare o eroare neașteptată, dar arată același mesaj "JSON Error". Acest lucru este greșit și, de asemenea, face Codul mai dificil de depanat.pentru a evita astfel de probleme, putem folosi tehnica „rethrowing”. Regula este simplă:

captura ar trebui să proceseze doar erorile pe care le cunoaște și să „regândească” toate celelalte.,tehnica „rethrowing” poate fi explicată mai detaliat ca:

  1. captura primește toate erorile.
  2. în blocul catch(err) {...}analizăm obiectul de eroareerr.
  3. dacă nu știm cum să ne descurcăm, facem throw err.

de Obicei, putem verifica tipul de eroare folosind instanceof operator:

putem obține, de asemenea, eroare de numele clasei din err.name proprietate. Toate erorile native o au. O altă opțiune este să citiți err.constructor.name.,

În codul de mai jos, vom folosi rethrowing astfel încât catch numai mânere SyntaxError:

eroare aruncat pe linia (*) din interiorul catch bloc „cade” de try..catch și poate fi prins printr-un exterior try..catch construct (dacă există), sau ucide script.

deci blocul catch gestionează de fapt numai erorile cu care știe să se ocupe și „omite” toate celelalte.,

exemplu de mai jos demonstrează cum un astfel de erori poate fi prins de un nivel mai mult de try..catch:

Aici readData știe doar cum să se ocupe de SyntaxError, în timp ce exterior try..catch știe cum să se ocupe de tot.

încercați … prinde … în cele din urmă

așteptați, asta nu e tot.

construcția try..catch poate avea încă o clauză de cod: finally.,

Dacă există, se execută în toate cazurile:

  • dupa try, daca nu au existat erori,
  • dupa catch, dacă nu au fost erori.

extinse sintaxa arată astfel:

try { ... try to execute the code ...} catch(e) { ... handle errors ...} finally { ... execute always ...}

Încercați să rulați acest cod:

try { alert( 'try' ); if (confirm('Make an error?')) BAD_CODE();} catch (e) { alert( 'catch' );} finally { alert( 'finally' );}

cod are două moduri de execuție:

  1. Dacă ai răspuns „Da” la „a Face o eroare?”, apoi try -> catch -> finally.,
  2. dacă spui „nu”, atunci try -> finally.

clauzafinally este adesea folosită atunci când începem să facem ceva și dorim să-l finalizăm în orice caz de rezultat.

de exemplu, vrem să măsurăm timpul în care o funcție de numere Fibonacci fib(n) ia. Desigur, putem începe măsurarea înainte de a rula și termina după aceea. Dar dacă există o eroare în timpul apelului de funcții? În special, implementarea fib(n) în codul de mai jos returnează o eroare pentru numere negative sau non-întregi.,

clauzafinally este un loc minunat pentru a termina măsurătorile indiferent de situație.

Aici finally garantează că timpul va fi măsurat în mod corect, în ambele situații – în caz de o execuție de succes fib și în caz de o eroare în ea:

puteți verifica prin rularea de cod cu intrarea 35 în prompt – se execută în mod normal, finally dupa try., Și apoi introduceți -1 – nu va fi o eroare imediată, iar execuția va dura 0ms. Ambele măsurători sunt efectuate corect.

cu alte cuvinte, funcția se poate termina cu return sau throw, asta nu contează. Clauza finally se execută în ambele cazuri.,

Variabile sunt locale interior try..catch..finally

vă Rugăm să rețineți că result și diff variabile în codul de mai sus sunt declarate înainte try..catch.

în caz Contrar, dacă ne-am declarat let în try bloc, ar fi vizibile numai în interiorul de ea.

try..finally

try..finally construct, fără catch clauză, este, de asemenea, util., Îl aplicăm atunci când nu vrem să gestionăm Erorile aici (lăsați-le să cadă), dar vrem să fim siguri că procesele pe care le-am început sunt finalizate.

function func() { // start doing something that needs completion (like measurements) try { // ... } finally { // complete that thing even if all dies }}

În codul de mai sus, o eroare interior try mereu cade, pentru că nu e catch. Dar finally funcționează înainte ca fluxul de execuție să părăsească funcția.

captură globală

mediu specific

informațiile din această secțiune nu fac parte din JavaScript-ul de bază.,

să ne imaginăm că avem o eroare fatală în afara try..catch, iar scenariul a murit. Ca o eroare de programare sau un alt lucru teribil.există o modalitate de a reacționa la astfel de evenimente? Este posibil să dorim să înregistrăm eroarea, să arătăm ceva utilizatorului (în mod normal nu văd mesaje de eroare) etc.

nu există niciunul în specificație, dar mediile îl oferă de obicei, deoarece este cu adevărat util. De exemplu, nod.js are process.on("uncaughtException") pentru asta. Și în browser putem atribui o funcție ferestrei speciale.,onerror proprietate, care va rula în cazul unei erori neprins.

sintaxa:

window.onerror = function(message, url, line, col, error) { // ...};

messagemesaj de Eroare.urlURL-ul scriptului unde s-a produs eroarea.line,colnumere de linie și coloană unde s-a produs eroarea.errorobiect de eroare.,

De exemplu:

rolul global handler window.onerror este, de obicei, nu pentru a recupera executarea script – probabil că e imposibil în cazul unei erori de programare, ci de a trimite mesaj de eroare pentru dezvoltatori.

funcționează astfel:

  1. ne înregistrăm la serviciu și obținem o bucată de JS (sau un URL de script) de la ei pentru a le insera pe pagini.
  2. că JS script stabilește un obicei window.onerror funcție.
  3. când apare o eroare, trimite o solicitare de rețea despre aceasta serviciului.
  4. ne putem conecta la interfața web a serviciului și putem vedea erori.,

rezumat

try..catch construct permite să se ocupe de erori de execuție. Acesta permite literalmente să” încercați „rularea codului și să” prindeți ” Erorile care pot apărea în el.

sintaxa este:

nu poate fi nici catch secțiunea sau nu finally, deci mai scurt constructe try..catch și try..finally sunt, de asemenea, valabil.

obiectele de eroare au următoarele proprietăți:

  • message – mesajul de eroare care poate fi citit de om.,
  • name – șirul cu nume de eroare (nume constructor de eroare).
  • stack (non-standard, dar bine acceptat)-stiva în momentul creării erorii.

Dacă o eroare obiect nu este necesar, putem omite folosind catch { în loc de catch(err) {.de asemenea, putem genera propriile erori folosind operatorul throw., Din punct de vedere tehnic, argumentul throw poate fi orice, dar de obicei e o eroare obiect moștenirea de la built-in Error clasa. Mai multe despre extinderea erorilor în capitolul următor.

Rethrowing este un foarte important model de eroare de manipulare: un catch bloc, de obicei, se așteaptă și știe cum să se ocupe în special de tip eroare, așa că ar trebui să rethrow erori nu știu.chiar dacă nu avem try..catch, majoritatea mediilor ne permit să configurăm un handler de erori „global” pentru a detecta erorile care „cad”., În browser, este window.onerror.

Leave A Comment