Fehlerbehandlung in JavaScript: try/catch und fortgeschrittene Techniken in Node.js

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Fehlerbehandlung in JavaScript: try/catch und mehr: Fortgeschrittenes Niveau



Fehlerbehandlung ist nicht nur der Schutz vor dem Absturz einer Anwendung, sondern ein grundlegender Aspekt beim Aufbau zuverlässiger und fehlertoleranter Systeme in JavaScript und Node.js. Die grundlegende Verwendung von try/catch ist jedem Entwickler bekannt, aber in realen Projekten, insbesondere auf der Serverseite, treten viele Nuancen auf: asynchrone Abläufe, Promise-Ketten, globale Fehler und die Notwendigkeit strukturierter, benutzerdefinierter Fehler. In diesem Artikel werden wir fortgeschrittene Techniken der Fehlerbehandlung behandeln, die Ihnen helfen, saubereren und vorhersagbareren Code in Node.js zu schreiben.



1. Tiefer Einstieg in try/catch und Asynchronität



Das klassische try/catch ist synchron. Es fängt Fehler innerhalb normaler Funktionen hervorragend ab, scheitert jedoch bei asynchronen Callbacks oder Promises ohne await. In Node.js, wo 90% des Codes asynchron ist, wird dies oft zur Ursache für "verschluckte" Ausnahmen.



Fehler: try/catch fängt den Fehler in setTimeout nicht

function dangerousAsync() {  setTimeout(() => {    throw new Error('Timer-Fehler!');  }, 1000);}

try { dangerousAsync();} catch (e) { console.log('Gefangen:', e.message); // Dieser Code wird NICHT ausgeführt}


In diesem Beispiel wird der Fehler außerhalb des try-Kontexts ausgelöst, und der Node.js-Prozess wird abnormal beendet. Der richtige Ansatz ist die Verwendung von Promises oder async/await.



Lösung: Asynchronen Code in ein Promise verpacken

function safeAsync() {  return new Promise((resolve, reject) => {    setTimeout(() => {      reject(new Error('Timer-Fehler!'));    }, 1000);  });}

(async () => { try { await safeAsync(); } catch (e) { console.log('Gefangen:', e.message); // Wird nach 1 Sekunde ausgeführt }})();


Die Hauptregel: Jede asynchrone Operation in ein Promise verpacken und await innerhalb von try/catch verwenden. Dies stellt sicher, dass der Fehler im richtigen Kontext abgefangen wird.



2. Benutzerdefinierte Fehlerklassen: Semantik und Kontext



Anstatt new Error('Irgendwas ist schiefgelaufen') auszulösen, erstellen Sie eine Hierarchie eigener Fehlerklassen. Dies ermöglicht es dem Handler, die Art des Fehlers zu verstehen und entsprechend zu reagieren (z. B. protokollieren, an das Monitoring senden oder dem Benutzer einen bestimmten HTTP-Status zurückzugeben).



class AppError extends Error {  constructor(message, statusCode = 500) {    super(message);    this.name = this.constructor.name;    this.statusCode = statusCode;    Error.captureStackTrace(this, this.constructor);  }}

class ValidationError extends AppError { constructor(message) { super(message, 400); }}

class DatabaseError extends AppError { constructor(message, originalError) { super(message, 503); this.originalError = originalError; // Ursprünglichen Fehler für Debugging speichern }}

// Verwendungfunction findUser(id) { if (!id) throw new ValidationError('Benutzer-ID ist erforderlich'); // ... Logik, die einen DatabaseError auslösen könnte}


Vorteile dieses Ansatzes:

  • Lesbarkeit: Der Klassenname sagt sofort etwas über die Art des Problems aus.
  • Routing: Im globalen Handler können Sie instanceof prüfen und die Antwortstrategie wählen.
  • Zusätzliche Felder: Sie können beliebige Daten hinzufügen (statusCode, originalError, userId usw.).


3. Globale Fehlerhandler in Node.js



Selbst bei sorgfältigster Kontrolle können unbehandelte Fehler nach außen dringen. In Node.js gibt es zwei wichtige Ereignisse, um sie abzufangen: uncaughtException und unhandledRejection

Blogs

Buchempfehlungen