Articles

Gestione degli errori, ” prova..catch”

Posted by admin

Non importa quanto siamo bravi a programmare, a volte i nostri script hanno errori. Possono verificarsi a causa dei nostri errori, un input inaspettato dell’utente, una risposta errata del server e per mille altri motivi.

Di solito, uno script “muore” (si ferma immediatamente) in caso di errore, stampandolo sulla console.

Ma c’è un costrutto di sintassi try..catch che ci permette di “catturare” gli errori in modo che lo script possa, invece di morire, fare qualcosa di più ragionevole.,

Il “try…catch” sintassi

try..catch costruire dispone di due blocchi principali: try e poi catch:

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

funziona in questo modo:

  1. in Primo luogo, il codice try {...} viene eseguito.
  2. Se non ci sono stati errori, alloracatch(err) viene ignorato: l’esecuzione raggiunge la fine ditry e va avanti, saltandocatch.,
  3. Se si verifica un errore, l’esecuzione di tryviene interrotta e il controllo scorre all’inizio di catch(err). La variabileerr (possiamo usare qualsiasi nome per essa) conterrà un oggetto error con dettagli su ciò che è successo.

Così, un errore all’interno del try {…} blocco non uccidere gli script – abbiamo la possibilità di gestire in catch.,

Diamo un’occhiata ad alcuni esempi.

try..catch funziona solo per errori di runtime

Per try..catch per funzionare, il codice deve essere eseguibile. In altre parole, dovrebbe essere JavaScript valido.

Non funzionerà se il codice è sintatticamente sbagliato, ad esempio ha parentesi graffe senza pari:

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

Il motore JavaScript prima legge il codice e poi lo esegue., Gli errori che si verificano nella fase di lettura sono chiamati errori” parse-time ” e sono irrecuperabili (dall’interno di quel codice). Questo perché il motore non riesce a capire il codice.

Quindi,try..catch può gestire solo gli errori che si verificano nel codice valido. Tali errori sono chiamati ” errori di runtime “o, a volte,”eccezioni”.

Error object

Quando si verifica un errore, JavaScript genera un oggetto contenente i dettagli su di esso., L’oggetto viene quindi passato come argomento a catch:

Per tutti gli errori incorporati, l’oggetto error ha due proprietà principali:

name Nome errore. Ad esempio, per una variabile indefinita che è "ReferenceError". message Messaggio testuale sui dettagli dell’errore.

Ci sono altre proprietà non standard disponibili nella maggior parte degli ambienti., Uno dei più utilizzati e supportati è:

stack Current call stack: una stringa con informazioni sulla sequenza di chiamate nidificate che hanno portato all’errore. Utilizzato per scopi di debug.

Per esempio:

Binding opzionale “catch”

Un’aggiunta recente
Questa è una recente aggiunta alla lingua. I vecchi browser potrebbero aver bisogno di polyfill.,

Se non abbiamo bisogno di dettagli errore, catch può omettere:

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

Uso di “try…catch”

esploriamo la vita reale caso di utilizzo di try..catch.

Come già sappiamo, JavaScript supporta il JSON.metodo parse (str) per leggere i valori codificati JSON.

Di solito viene utilizzato per decodificare i dati ricevuti in rete, dal server o da un’altra fonte.,

Lo riceviamo e chiamiamoJSON.parse in questo modo:

Puoi trovare informazioni più dettagliate su JSON nei metodi JSON, capitolo toJSON.

Se json è malformato, JSON.parse genera un errore, quindi lo script “muore”.

Dovremmo essere soddisfatti di questo? Certo che no!

In questo modo, se qualcosa non va con i dati, il visitatore non lo saprà mai (a meno che non apra la console degli sviluppatori). E alla gente non piace davvero quando qualcosa “muore” senza alcun messaggio di errore.,

Usiamotry..catchper gestire l’errore:

Qui usiamo il bloccocatch solo per mostrare il messaggio, ma possiamo fare molto di più: inviare una nuova richiesta di rete, suggerire un’alternativa al visitatore, inviare informazioni sull’errore a un impianto di registrazione, … . Tutto molto meglio che morire.

Lanciare i nostri errori

Cosa succede sejson è sintatticamente corretto, ma non ha una proprietàname richiesta?,

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

JSON.parse viene eseguito normalmente, ma l’assenza di name è in realtà un errore per noi.

Per unificare la gestione degli errori, useremo l’operatore throw.

Operatore”Throw”

L’operatorethrow genera un errore.

La sintassi è:

throw <error object>

Tecnicamente, possiamo usare qualsiasi cosa come oggetto di errore., Potrebbe essere anche una primitiva, come un numero o una stringa, ma è meglio usare oggetti, preferibilmente con proprietà name e message (per rimanere in qualche modo compatibili con gli errori incorporati).

JavaScript ha molti costruttori incorporati per errori standard: Error, SyntaxError, ReferenceError, TypeError e altri. Possiamo usarli anche per creare oggetti di errore.,

La loro sintassi è:

<"2c743f6101">

Per errori incorporati (non per oggetti, solo per errori), la proprietà name è esattamente il nome del costruttore. Emessage è preso dall’argomento.,

Per esempio:

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

vediamo che tipo di errore JSON.parse genera:

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

Come si può vedere, che il SyntaxError.

E nel nostro caso, l’assenza di name è l’errore, poiché gli utenti devono avere un name.,

Quindi buttiamolo:

Nella riga(*), l’operatorethrow genera unSyntaxError con il datomessage, allo stesso modo di JavaScript genererebbe esso stesso. L’esecuzione di try si interrompe immediatamente e il flusso di controllo salta in catch.

Ora catch è diventato un unico posto per tutta la gestione degli errori: sia per JSON.parse e altri casi.,

Rethrowing

Nell’esempio sopra usiamotry..catch per gestire dati errati. Ma è possibile che si verifichi un altro errore imprevisto all’interno del blocco try {...}? Come un errore di programmazione (la variabile non è definita) o qualcos’altro, non solo questa cosa “dati errati”.

Per esempio:

Certo, tutto è possibile! I programmatori fanno errori. Anche nelle utility open-source utilizzate da milioni di persone per decenni – improvvisamente si può scoprire un bug che porta a terribili hack.,

Nel nostro caso, try..catch viene inserito per rilevare errori di “dati errati”. Ma per sua natura,catch ottiene tutti gli errori datry. Qui ottiene un errore inaspettato, ma mostra ancora lo stesso messaggio"JSON Error". Questo è sbagliato e rende anche il codice più difficile da eseguire il debug.

Per evitare tali problemi, possiamo utilizzare la tecnica “rethrowing”. La regola è semplice:

Catch dovrebbe elaborare solo errori che conosce e “ripensare” tutti gli altri.,

La tecnica “rethrowing” può essere spiegata in modo più dettagliato come:

  1. Catch ottiene tutti gli errori.
  2. Nel bloccocatch(err) {...} analizziamo l’oggetto di erroreerr.
  3. Se non sappiamo come gestirlo, facciamo throw err.

Di solito, possiamo controllare il tipo di errore usando l’operatore instanceof:

Possiamo anche ottenere il nome della classe di errore dalla proprietà err.name. Tutti gli errori nativi ce l’hanno. Un’altra opzione è leggere err.constructor.name.,

Nel codice riportato di seguito, usiamo generazione ripetuta in modo che catch gestisce solo SyntaxError:

L’errore di lancio on line (*) dall’interno catch blocco “cade” di try..catch e può essere catturato da un esterno try..catch costruire (se esiste), o che uccide lo script.

Quindi il bloccocatch gestisce in realtà solo errori che sa come gestire e “salta” tutti gli altri.,

L’esempio seguente mostra come tali errori possono essere rilevati da un altro livello di try..catch:

Qui readData sa solo come gestire SyntaxError, mentre l’esterno try..catch sa come gestire tutto.

prova catch cattura finally finalmente

Aspetta, non è tutto.

Il costrutto try..catch può avere un’altra clausola di codice: finally.,

Se esiste, viene eseguito in tutti i casi:

  • dopotry, se non ci sono stati errori,
  • dopocatch, se ci sono stati errori.

La sintassi estesa di simile a questo:

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

Provare a eseguire questo codice:

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

Il codice ha due modalità di esecuzione:

  1. Se la risposta è “Sì” per “Fare un errore?”, quindi try -> catch -> finally.,
  2. Se dici “No”, allora try -> finally.

La clausola finally viene spesso utilizzata quando iniziamo a fare qualcosa e vogliamo finalizzarla in ogni caso di esito.

Ad esempio, vogliamo misurare il tempo che una funzione di numeri di Fibonaccifib(n) richiede. Naturalmente, possiamo iniziare a misurare prima che venga eseguito e finire in seguito. Ma cosa succede se c’è un errore durante la chiamata alla funzione? In particolare, l’implementazione di fib(n) nel codice seguente restituisce un errore per numeri negativi o non interi.,

La clausolafinally è un ottimo posto per completare le misurazioni, indipendentemente da cosa.

finally garantisce che il tempo sarà misurato correttamente in entrambe le situazioni – in caso di esito positivo dell’esecuzione del fib e in caso di errore:

È possibile controllare l’esecuzione del codice, con l’immissione di 35 in prompt esegue normalmente finally dopo try., E poi inserisci -1 – ci sarà un errore immediato e l’esecuzione prenderà0ms. Entrambe le misurazioni sono eseguite correttamente.

In altre parole, la funzione potrebbe finire conreturnothrow, non importa. La clausolafinally viene eseguita in entrambi i casi.,

Le variabili sono locali all’interno di try..catch..finally

Si prega di notare che result e diff le variabili nel codice sopra sono dichiarate prima di try..catch.

Altrimenti, se dichiarassimolet intry blocco, sarebbe visibile solo all’interno di esso.

Iltry..finally costrutto, senza catch clausola, è anche utile., Lo applichiamo quando non vogliamo gestire gli errori qui (lasciarli cadere), ma vogliamo essere sicuri che i processi che abbiamo iniziato siano finalizzati.

Nel codice precedente, un errore all’interno ditry cade sempre, perché non c’è catch. Mafinally funziona prima che il flusso di esecuzione lasci la funzione.

Cattura globale

Ambiente specifico

Le informazioni di questa sezione non fanno parte del JavaScript principale.,

Immaginiamo di avere un errore fatale al di fuori di try..catch, e lo script è morto. Come un errore di programmazione o qualche altra cosa terribile.

C’è un modo per reagire a tali eventi? Potremmo voler registrare l’errore, mostrare qualcosa all’utente (normalmente non vedono i messaggi di errore), ecc.

Non ce n’è nella specifica, ma gli ambienti di solito lo forniscono, perché è davvero utile. Ad esempio, Nodo.js haprocess.on("uncaughtException") per quello. E nel browser possiamo assegnare una funzione alla finestra speciale.,proprietà onerror, che verrà eseguito in caso di errore non rilevato.

La sintassi:

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

message Messaggio di errore. url URL dello script in cui si è verificato l’errore. line,col Numeri di riga e colonna in cui si è verificato un errore. error Oggetto di errore.,

Ad esempio:

Il ruolo del gestore globale window.onerror di solito non è quello di recuperare l’esecuzione dello script – probabilmente impossibile in caso di errori di programmazione, ma di inviare il messaggio di errore agli sviluppatori.

Funzionano così:

  1. Ci registriamo al servizio e otteniamo un pezzo di JS (o un URL di script) da inserire nelle pagine.
  2. Che lo script JS imposta una funzione window.onerror personalizzata.
  3. Quando si verifica un errore, invia una richiesta di rete al servizio.
  4. Possiamo accedere all’interfaccia web del servizio e vedere gli errori.,

Riepilogo

Il costruttotry..catch consente di gestire gli errori di runtime. Permette letteralmente di” provare “a eseguire il codice e” catturare” gli errori che possono verificarsi in esso.

La sintassi è:

Non ci possono essere sezioni catch o no finally, quindi sono validi anche costrutti più brevi try..catch e try..finally.

Gli oggetti Error hanno le seguenti proprietà:

  • message – il messaggio di errore leggibile dall’uomo.,
  • name – la stringa con il nome dell’errore (error constructor name).
  • stack (non standard, ma ben supportato)-lo stack al momento della creazione dell’errore.

Se non è necessario un oggetto error, possiamo ometterlo usando catch {invece di catch(err) {.

Possiamo anche generare i nostri errori utilizzando l’operatore throw., Tecnicamente, l’argomento di throw può essere qualsiasi cosa, ma di solito è un oggetto error che eredita dalla classe Error incorporata. Maggiori informazioni sull’estensione degli errori nel prossimo capitolo.

Il Rethrowing è un modello molto importante di gestione degli errori: un blocco catch di solito si aspetta e sa come gestire il particolare tipo di errore, quindi dovrebbe ripetere gli errori che non conosce.

Anche se non abbiamo try..catch, la maggior parte degli ambienti ci consente di impostare un gestore di errori “globale” per rilevare errori che “cadono”., In-browser, questo è window.onerror.

Leave A Comment