Prova avanzata/catch/finally in Javascript e Typescript

Dai un'occhiata dettagliata all'implementazione di un blocco try-catch-finally

Gestione degli errori in Javascript e Typescript

Ogni volta che si verifica un errore in fase di esecuzione, viene "generato" in Javascript e Typescript, come nella maggior parte dei linguaggi di programmazione. Gli errori generati non gestiti porteranno a un arresto anomalo della tua app o del tuo servizio, quindi la peggiore esperienza utente possibile. Se si verifica un errore, tutti i progressi non salvati vengono persi e gli utenti potrebbero potenzialmente avviare un lungo processo (ad esempio, se un utente si stesse registrando a una piattaforma fornendo molte informazioni) da capo. Il risultato è che molto probabilmente quegli utenti non utilizzeranno mai più il tuo prodotto, poiché la fiducia è stata persa.

Per gestire tali casi, è possibile "catturare" un errore. Per rilevare errori in Javascript e Typescript, è sufficiente avvolgere il codice in un blocco "try", seguito da un blocco "catch".

async function getData(){
  try {
    // Call a dummy async 'fetch'-functoin
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error };
  }
}

// ... later in your code ....

const { result, error } = await getData();

if (error){
  // ... handle error case.
}

// Access the results.

Il risultato è che l'errore non si propagherà attraverso l'intero sistema, il che porta all'arresto anomalo, ma verrà gestito direttamente nell'ambito del codice. L'app o il servizio non si arresta in modo anomalo e può essere applicata una strategia di mitigazione per elaborare l'errore.

Movimentazione speciale con il blocco “finally”

Come ulteriore passaggio per gestire gli errori, Javascript e Typescript forniscono una parola chiave aggiuntiva "finalmente". Tale blocco "finalmente" esegue qualsiasi codice all'interno del suo ambito dopo che sia il blocco "try" che il blocco "catch" sono stati eseguiti (se si è verificato un errore).

// This function is absolutely save
// to call. It fetches some data and 
// optionally catches a potential error.
//
// After everything's done, a 'finally'
// sends the error to our backend for logs,
// if there was any.
async function getData(){
  // In this case, we store the result
  // and error in mutable variables,
  // then return both.
  let result: Result;
  let error: Error;
  
  try {
    // Call a dummy async 'fetch'-function
    result = await fetch();
  } catch(e) {
    error = e;
  } finally {
    // After the whole try/catch has been
    // processed, we can log the error.
    if(error){
      await trackErrorInCloud(error);
    }
  }
  
  return { result, error };
}

// ... same as before ...

Ma aspetta, c'è di più! Sapevi che il blocco "finally" viene eseguito anche se restituisci un risultato nel blocco "try" o "catch"? Ecco un esempio di cosa intendo con questo.

// Same as the example before, but
// now we directly return from within
// each code block. And this is where
// a side effect can happen.
async function getData(){
  try {
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error }
  } finally {
    //
    // WATCH OUT!
    //
    // Just for demo purpose, but this
    // line of code will override both
    // the return in 'try' as well as 'catch'!
    //
    // Returning inside of 'finally' is therefore
    // dangerous and will lead to hard-to-debug 
    // issues.
    return { finally: true };
  }
}

// data === { finally: true }
const data = await getData();
// Here's a better use case for
// finally.
async function getData(){
  let error: Error;
  
  try {
    const result = await fetch();
    return { result };
  } catch(e) {
    error = e;
    return { error }
  } finally {
    // No return in finally,
    // so it's safe to use.
    if(error){
      await logInCloud()
    }
  }
}

// if no error === { result: ... }
// if error === { error: ... }
const data = await getData();

Sommario

Come hai visto, la gestione degli errori in Javascript e Typescript è abbastanza semplice ed evita un crash completo della tua applicazione. La gestione speciale dei risultati restituiti nei blocchi "try" e "catch" è utile quando si utilizza il blocco "finally", ma non dovrebbe essere abusata per evitare di implementare il codice in uno stile anti-pattern.

Suggerimenti

Correlati

Lingue