Fortgeschrittenes try/catch/finally in Javascript und Typescript

Werfen Sie einen detaillierten Blick auf die Implementierung eines Try-Catch-Finally-Blocks

Fehlerbehandlung in Javascript & Typescript

Wenn zur Laufzeit ein Fehler auftritt, wird er in Javascript und Typescript „geworfen“, wie es in den meisten Programmiersprachen der Fall ist. Unbehandelte geworfene Fehler führen zu einem Absturz Ihrer App oder Ihres Dienstes und somit zu der schlechtesten Benutzererfahrung. Wenn ein Fehler auftritt, gehen alle nicht gespeicherten Fortschritte verloren und Benutzer können möglicherweise einen langen Prozess erneut starten (z. B. wenn sich ein Benutzer bei einer Plattform anmeldet, indem er viele Informationen bereitstellt). Das Ergebnis ist, dass diese Benutzer Ihr Produkt höchstwahrscheinlich nie wieder verwenden werden, da das Vertrauen verloren gegangen ist.

Um solche Fälle zu behandeln, kann ein Fehler „abgefangen“ werden. Um Fehler in Javascript und Typescript abzufangen, packen Sie Ihren Code einfach in einen „try“-Block, gefolgt von einem „catch“-Block.

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.

Das Ergebnis ist, dass sich der Fehler nicht im gesamten System ausbreitet, was zum Absturz führt, sondern direkt im Rahmen Ihres Codes behandelt wird. Die App oder der Dienst stürzt nicht ab und es kann eine Risikominderungsstrategie zur Verarbeitung des Fehlers angewendet werden.

Sonderbehandlung mit dem „finally“-Block

Als zusätzlichen Schritt zur Fehlerbehandlung bieten Javascript und Typescript ein zusätzliches „finally“-Schlüsselwort. Ein solcher „finally“-Block führt jeden Code innerhalb seines Geltungsbereichs aus, nachdem sowohl der „try“-Block als auch der „catch“-Block ausgeführt wurden (falls ein Fehler aufgetreten ist).

// 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 ...

Aber warten Sie, es gibt noch mehr! Wussten Sie, dass der „finally“-Block auch dann ausgeführt wird, wenn Sie im „try“- oder „catch“-Block ein Ergebnis zurückgeben? Hier ist ein Beispiel dafür, was ich damit meine.

// 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();

Zusammenfassung

Wie Sie gesehen haben, ist die Handhabung von Fehlern in Javascript und Typescript recht einfach und vermeidet einen vollständigen Absturz Ihrer Anwendung. Die spezielle Behandlung der Rückgabe von Ergebnissen in den "try"- und "catch"-Blöcken ist gut zu wissen, wenn man den "finally"-Block verwendet, sollte aber nicht missbraucht werden, um Ihren Code nicht in einem Anti-Pattern-Stil zu implementieren.

Vorschläge

Verwandt

Sprachen