try-catch in javascript ... non è una buona pratica?

66

Esiste una disposizione per il blocco try-catch in javascript . Mentre in Java o in qualsiasi altra lingua è obbligatorio avere la gestione degli errori, non vedo nessuno che li usi in javascript per una maggiore estensione. Non è una buona pratica o semplicemente non ne abbiamo bisogno in javascript?

    
posta akp 13.04.2012 - 18:19
fonte

7 risposte

65

Si dovrebbero evitare errori di throw come metodo per passare le condizioni di errore nelle applicazioni.

L'istruzione throw deve essere utilizzata solo "Per questo non dovrebbe mai accadere, crash e masterizzazione. Non recuperare in modo elegante in alcun modo"

try catch tuttavia viene utilizzato in situazioni in cui oggetti host o ECMAScript possono generare errori.

Esempio:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

I consigli nella community node.js consistono nel passare gli errori in giro nei callback (poiché gli errori si verificano solo per operazioni asincrone) come primo argomento

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

Ci sono anche altri problemi come try / catch è molto costoso ed è brutto e semplicemente non funziona con operazioni asincrone.

Quindi, poiché le operazioni sincrone non devono generare un errore e non funziona con operazioni asincrone, nessuno usa try catch eccetto per errori lanciati da oggetti host o ECMAScript

    
risposta data 13.04.2012 - 18:30
fonte
32

Try / catch in Javascript non è così a prova di proiettile come in altre lingue, a causa della natura asincrona di Javascript. Considera questo snippet:

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

Il problema è che il flusso di controllo lascia il blocco try prima che venga eseguito do_something_that_throws() , quindi l'errore lanciato all'interno del callback non viene mai catturato.

Quindi try / catch è fondamentalmente inappropriato in molti casi, e non è sempre ovvio se qualcosa esegue il codice in modo asincrono o meno. Fortunatamente, javascript con il suo peculiare idioma di callback asincrono a thread singolo e il suo supporto per le chiusure effettive fornisce un'alternativa elegante: la gestione degli errori di stile a passaggio continuo. Passa semplicemente la risposta corretta a qualsiasi errore come funzione, ad esempio:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);
    
risposta data 13.04.2012 - 23:44
fonte
21

Molte di queste risposte sono un po 'vecchie e non tengono conto delle nuove funzionalità di ES7 async e await .

Usando async / await ora puoi ottenere il flusso di controllo asincrono come vuoi:

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: '[email protected]', subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

Ulteriori informazioni su async / await qui . Puoi utilizzare async / await ora usando babel .

    
risposta data 16.11.2015 - 00:13
fonte
15

try-catch in javascript è altrettanto valido e utile come in qualsiasi altro linguaggio che li implementa. C'è uno dei motivi principali per cui non è usato tanto in javascript come in altre lingue. La stessa ragione per cui javascript è visto come un brutto linguaggio di scripting, è la stessa ragione per cui la gente pensa che i programmatori javascript non siano dei veri programmatori:

  • Javascript è un linguaggio incredibilmente accessibile e pervasivo

Il semplice fatto che così tante persone siano esposte a javascript (in virtù dell'unica lingua supportata dai browser) significa che hai un sacco di codice non professionale. Naturalmente ci sono anche molti motivi minori:

  • alcune cose in javascript sono asincrone e quindi non sono in grado di catch (roba asincrona)
  • ci sono state molte chiacchiere esagerate su come il try-catch abbia un enorme successo in termini di prestazioni. Ha un po 'di hit per le prestazioni , ma per la maggior parte del codice, ne vale la pena .
  • javascript è stato (sfortunatamente) implementato in un modo che spesso ignora silenziosamente gli errori (modificando automaticamente le stringhe sui numeri, ad esempio)

Indipendentemente, si dovrebbe usare try-catch dovrebbe , ma ovviamente si dovrebbe impara come usarli correttamente - come tutto il resto nella programmazione.

    
risposta data 24.05.2014 - 21:11
fonte
6

Credo che gran parte del motivo per cui try..catch sia raro in JavaScript è dovuto al fatto che il linguaggio ha una tolleranza piuttosto elevata per l'errore. La maggior parte delle situazioni può essere gestita utilizzando i controlli del codice, le impostazioni predefinite e gli eventi asincroni. In alcuni casi, semplicemente utilizzando un modello si evitano problemi:

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

Alcuni dei principali problemi in altre lingue che causano la comparsa di eccezioni semplicemente non esistono in JS. Il casting di tipo non è necessario per la maggior parte del tempo. Invece, il metodo preferito è tipicamente il controllo delle funzionalità (applica una particolare interfaccia):

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

Con l'aggiunta di async / await alla lingua, try..catch sta diventando più prevalente. Promette di essere la forma asincrona di try..catch , ha senso che ci si aspetti:

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

invece di essere scritto come:

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}
    
risposta data 13.04.2012 - 19:27
fonte
3

Forse un altro motivo try / catch non è usato molto in Javascript, il costrutto non era disponibile nelle primissime versioni di Javascript ... è stato aggiunto in seguito.

Di conseguenza, alcuni browser meno recenti non lo supportano. (In effetti, potrebbe causare un errore di parser / sintassi in alcuni browser più vecchi, qualcosa che è più difficile da "programmare in modo difensivo" rispetto alla maggior parte degli altri tipi di errori.)

Ancora più importante, dal momento che inizialmente non era disponibile, le funzioni integrate di Javascript che erano state inizialmente rilasciate (quelle che chiamerebbero le funzioni di "biblioteca" in molte lingue) non ne fanno uso. (Non funziona molto bene per "catturare" un errore da someobject.somefunction () se non "lancia" ma invece restituisce "null" quando incontra un problema.)

Ancora un'altra possibile ragione è che il meccanismo try / catch non sembra essere necessario inizialmente (e non sembra ancora così utile). È davvero necessario solo quando le chiamate vengono annidate regolarmente in diversi livelli; solo il ritorno di una sorta di ERRNO funzionerebbe bene per le chiamate dirette (anche se per renderlo davvero utile ogni volta che è disponibile, la migliore pratica nella maggior parte delle lingue è usarla ovunque piuttosto che solo su chiamate profondamente annidate). Poiché inizialmente la logica di Javascript doveva essere piccola e semplice (dopotutto, è solo un'aggiunta a una pagina web :-), non ci si aspettava che le chiamate di funzione fossero profondamente annidate, e quindi un meccanismo try / catch non sembrava necessario.

    
risposta data 22.05.2013 - 05:12
fonte
0

Credo che non vengano utilizzati così tanto perché il lancio di eccezioni nel codice lato client Javascript rende più difficile il debug di una pagina.

Invece di lanciare eccezioni, generalmente preferisco mostrare una casella di avviso, (cioè alert("Error, invalid..."); )

Potrebbe sembrare strano, ma gli errori Javascript si verificano sul lato client, se un cliente utilizza una pagina creata dall'utente e la pagina genera un'eccezione, a meno che il cliente non sia un programmatore esperto di tecnologia non è mai in grado di dirti quale sia il problema.

Ti chiamerà solo per dire: "Ehi, la pagina X non funziona!", e poi spetterà a te scoprire cosa è andato storto e dove nel codice .

Usando la casella di avviso invece è più probabile che chiami e dica qualcosa come: "Ehi, quando clicco sul pulsante A della pagina X viene visualizzata una finestra che dice ..." , fidati, sarà molto più facile trovare il bug.

    
risposta data 29.12.2018 - 20:36
fonte

Leggi altre domande sui tag