2015-07-28 14 views
8

Ho ereditato una base di codice sul posto di lavoro che contiene una dozzina di esempi del seguente schema:Le promesse in AngularJS catturano ogni eccezione/errore?

var promise = null; 
try { 
    promise = backendService.getResults(input); 
} 
catch (exception) { 
    console.err(exception); 
} 
if (promise !== null) { 
    promise.then(function (response) { 
     // do stuff 
    }) 
    .catch(function (error) { 
     console.err(error); 
    }); 
} 

Dove backendService è un servizio angolare che a sua volta chiama un servizio REST attraverso $http.

Quindi, ecco la mia domanda: è che provare/prendere davvero necessario? Ci sarà mai qualche scenario in cui viene generato un particolare errore/eccezione che non riesce a intercettare lo .catch della promessa?

Questa è stata oggetto di un po 'di dibattito sulla squadra per tutta la mattina, e l'unica soluzione che è venuta in mente è che non lo facciamo pensano è necessario, ma (a) la modifica si rompe i test che sono stati scritti al suo fianco (che dovrebbero anche essere modificati), e (b) bene ... è la codifica difensiva, giusto? Non è una brutta cosa.

I meriti di preoccuparsi effettivamente di refactoring nel dimenticatoio quando ci sono cose più importanti da fare non sono quello che sto chiedendo, però. Voglio solo sapere se è un modello ragionevole quando le promesse vengono passate in questo modo (in AngularJS in particolare, se questo fa la differenza), o solo la paranoia.

+0

la sua non è necessario. puoi avere solo il tuo 'then()' e 'catch()' –

+0

mi sembra che sia solo parzialmente utile. Se si dispone di un'eccezione nel codice che attiva l'XHR (presumibilmente) per ottenere i risultati, questo codice verrà catturato, ma in genere quel codice è molto più noto e non soggetto alle eccezioni di runtime. La parte difficile è la risposta del server: è molto più probabile che ci sia un'eccezione a causa del fatto che il servizio restituisce qualcosa che non ti aspetti. Questo sarebbe gestito dal rifiuto della promessa. Non penso che il try/catch sia necessario se stai gestendo 'input' in modo sicuro (normalmente) nel tuo servizio. – pherris

+1

Sarebbe relativamente facile da testare. Inizia introducendo errori di sintassi nel metodo di vario tipo, sia prima della chiamata $ http che all'interno della sua callback, e poi finisci con il test degli errori http come 404 500 e l'errore CORS. La mia ipotesi sarebbe che. Cattura cattura tutto dopo l'avvio della richiesta http e la promessa viene restituita, ma non prima. –

risposta

4

Le promesse in AngularJS rilevano ogni eccezione/errore?

No. Solo eccezioni generate dall'interno then/catchcallback sono catturati automaticamente. Tutti gli errori che accadono al di fuori di essi dovranno essere gestiti in modo esplicito.

Si verificherà mai uno scenario in cui viene generato un particolare errore/eccezione che non riesce a intercettare il valore della promessa .catch?

Sì. La chiamata backendService.getResults(input) potrebbe non restituire una promessa, ma può generare un'eccezione. Oppure non arriva nemmeno così lontano quando backendService è nullo, e avrai un ReferenceError o .getResults non è una funzione e riceverai un TypeError.

è che provare/prendere davvero necessario?

Non proprio. In quest'ultimo caso, il tuo codice ha un grave errore, probabilmente non ti interessa buttare e schiantarti. Il primo caso, che i lanci di backendService.getResults(input), è pesantemente disprezzato. Asynchronous functions should never throw ma restituisce solo promesse - esattamente per il motivo che non è necessario scrivere due istruzioni di gestione degli errori allora.

beh ... è la codifica difensiva, giusto? Non è una brutta cosa.

Sì, praticamente. Ma è discutibile qui. Un'eccezione sincrona è davvero inattesa qui, non solo un servizio il cui errore può essere gestito. Il messaggio di registrazione nel blocco catch dovrebbe essere quello.

Si noti che non è abbastanza difensivo. Non rileva l'errore probabilmente più probabile in cui restituisce getResults(), ma qualcosa che non è una promessa. Chiamando .then() su quello potrebbe buttare. Allo stesso modo, il if (promise !== null) è dubbio, poiché si nasconde quando null viene restituito erroneamente (in questo caso potrebbe davvero essere necessario try-catch-else).

+0

Al tuo ultimo paragrafo: Scusa, quello è stato un mio errore. Ho modificato il blocco di codice nella mia domanda per chiarire. La dichiarazione di 'promise' prima del tentativo è in realtà inizializzandola su' null'. – daemonaka

+0

Per il resto. Grazie, questo è praticamente quello che ho capito. 'backendService' è tanto sotto il mio controllo ora quanto il codice che lo chiama, e posso dirti che restituisce assolutamente una promessa e che getterebbe sempre e solo se accadesse qualcosa di catastrofico e incredibilmente improbabile. Come se interi file fossero lasciati fuori dalla build. * Non * contiene la parola 'throw', e se lo facesse l'avrei rimosso per la ragione esatta che descrivi. A proposito, mi piace la frase "pesantemente disprezzata". Si adatta abbastanza bene. – daemonaka

1

è che provare/prendere davvero necessario?

Non proprio. Finché il tuo backendService.getResults() restituisce una promessa. Come return $http(...)

Ci sarà mai qualsiasi scenario in cui un particolare errore/eccezione viene lanciata che .catch della promessa non riesce a catturare?

Io non la penso così, dal momento che qualsiasi errore sarà una promessa respinto, cadrà nella vostra .catch() gestore

bene ... è la codifica difensiva, giusto? Non è una brutta cosa.

Dipende ... Javascript try/catch ha alcuni problemi di prestazioni. Quindi, se si sta utilizzando solo per il gusto di fare in modo, è possibile rimuovere it :)

fare un ulteriore sguardo alle discussioni try-catch qui se lo si desidera: Javascript Try-Catch Performance Vs. Error Checking Code

Problemi correlati