TypeScript-Fehlerbehandlung
Die Fehlerbehandlung ist ein wichtiger Bestandteil, um die Robustheit von Programmen zu gewährleisten.
TypeScript bietet ein leistungsstarkes Typsystem, das Entwicklern helfen kann, Fehler besser zu behandeln und zu vermeiden.
Dieser Artikel stellt gängige Fehlerbehandlungsmuster und Best Practices in TypeScript vor.
SVG-Diagramm: Ansätze zur Fehlerbehandlung
Warum gute Fehlerbehandlung nötig ist
Jedes Programm kann auf Fehlersituationen stoßen, wie fehlgeschlagene Netzwerkanfragen, fehlende Dateien, ungültige Benutzereingaben und so weiter.
Eine gute Fehlerbehandlung kann Programmabstürze verhindern, freundliche Fehlermeldungen bereitstellen und Entwicklern helfen, Probleme zu lokalisieren.
Das Typsystem von TypeScript kann potenzielle Probleme zur Kompilierzeit finden und Laufzeitfehler reduzieren.
Konzepterklärung:Es gibt zwei Hauptarten, Fehler zu behandeln: Ausnahmebehandlung (try-catch) und Rückgabewertbehandlung (Result-Typ). Erstere löst Ausnahmen aus, um Fehler anzuzeigen, während letztere Fehlerinformationen über Rückgabewerte transportiert.
Benutzerdefinierte Fehlertypen
Erstelle benutzerdefinierte Fehlertypen, indem du die Error-Klasse erweiterst, sodass sie mehr Fehlerinformationen tragen können.
Dies macht die Fehlerbehandlung präziser und strukturierter.
Beispiel
// Die integrierte Error-Klasse erweitern und einen Fehlercode hinzufügen
class AppError extends Error {
// Fehlercode für programmatische Fehlerbehandlung
Code: string;
// Konstruktor
constructor(message: string, code: string) {
super(message); // Rufe den Konstruktor der Elternklasse auf
this.name = "AppError"; // Setze den Fehlernamen
this.code = code; // Speichere den Fehlercode
}
}
// Sichere Divisionsfunktion
function divide(a: number, b: number): number {
// Prüfen, ob der Divisor null ist
if (b === 0) {
// Benutzerdefinierten Fehler auslösen
throw new AppError("Division durch null nicht möglich", "DIVIDE_BY_ZERO");
}
return a / b;
}
// Verwende try-catch, um den Fehler abzufangen
try {
var result = divide(10, 0);
} catch (error) {
// Fehlertyp prüfen
if (error instanceof AppError) {
console.log("Anwendungsfehler: " + error.message + ", Code: " + error.code);
} else {
console.log("Unbekannter Fehler: " + error);
}
}
Ausgabe:
应用错误: Cannot divide by zero, 代码: DIVIDE_BY_ZERO
Fehlercode:Das Hinzufügen von Codes zu Fehlern hilft dem Programm, verschiedene Arten von Fehlern präziser zu behandeln.
Result-Typ zur Vermeidung von Ausnahmen
Ein weiterer Ansatz zur Fehlerbehandlung ist die Verwendung des Result-Typs.
Er übermittelt Fehlerinformationen über Rückgabewerte, anstatt Ausnahmen auszulösen. Dieser Ansatz ist in der funktionalen Programmierung üblich.
Beispiel
// Bei Erfolg enthält er ok: true und einen Wert; im Fehlerfall enthält er ok: false und einen Fehler
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
// Divisionsfunktion mit dem Result-Typ
function safeDivide(a: number, b: number): Result<number, string> {
// Prüfen, ob der Divisor null ist
if (b === 0) {
// Ein Fehlerergebnis zurückgeben
return { ok: false, error: "Division durch Null nicht möglich" };
}
// Ein Erfolgsergebnis zurückgeben
return { ok: true, value: a / b };
}
// Die Funktion aufrufen und das Ergebnis verarbeiten
var result = safeDivide(10, 2);
// Basierend auf dem Result-Typ verarbeiten
if (result.ok) {
console.log("Ergebnis: " + result.value);
} else {
console.log("Fehler: " + result.error);
}
Ausgabe:
结果: 5
Vorteile:Der Result-Typ macht die Fehlerbehandlung explizit; Aufrufer müssen mögliche Fehler behandeln und können sie nicht ignorieren.
Fehlerbehandlung in asynchronen Funktionen
In asynchronen Funktionen ist die Fehlerbehandlung besonders wichtig.
Sie können try-catch oder den Result-Typ verwenden, um Fehler in asynchronen Operationen zu behandeln.
Beispiel
interface User {
id: number;
name: string;
}
// Simuliere eine asynchrone Funktion zum Abrufen eines Benutzers
async function fetchUser(id: number): Promise<Result<User, Error>> {
try {
// Simuliere eine Netzwerkanfrage
var response = await fetch("/api/users/" + id);
var user = await response.json();
// Ein Erfolgsergebnis zurückgeben
return { ok: true, value: user };
} catch (error) {
// Ein Fehlerergebnis zurückgeben
return { ok: false, error: error as Error };
}
}
// Hauptfunktion
async function main() {
// Asynchrone Funktion aufrufen
var result = await fetchUser(1);
// Das Ergebnis verarbeiten
if (result.ok) {
console.log("Benutzer: " + JSON.stringify(result.value));
} else {
console.log("Fehler: " + result.error.message);
}
}
// Hauptfunktion ausführen
main();
Ausgabe:
User: {"id":1,"name":"Alice"}
Tipp:Das try-catch in einer async-Funktion fängt jeden Fehler ab, der von await-Ausdrücken geworfen wird.
Allgemeiner Wrapper zur Fehlerbehandlung
Du kannst eine allgemeine Funktion zur Fehlerbehandlung erstellen, um die Fehlerbehandlung in asynchronem Code zu vereinfachen.
Beispiel
// Eine async-Funktion annehmen und einen Result-Typ zurückgeben
async function withErrorHandling<T>(
fn: () => Promise<T>
): Promise<Result<T, Error>> {
try {
// Führe die übergebene async-Funktion aus
var data = await fn();
// Ein Erfolgsergebnis zurückgeben
return { ok: true, value: data };
} catch (error) {
// Ein Fehlerergebnis zurückgeben
return { ok: false, error: error as Error };
}
}
// Allgemeine Fehlerbehandlung verwenden
// Datenabruf simulieren
var result = await withErrorHandling(async function() {
var response = await fetch("/api/data");
return response.json();
});
// Basierend auf dem Ergebnis behandeln
if (result.ok) {
console.log("Daten: " + JSON.stringify(result.value));
} else {
console.error("Error:", result.error);
}
Bewährte Praxis:Das Kapseln allgemeiner Fehlerbehandlungslogik reduziert Codeduplizierung und verbessert die Wartbarkeit des Codes.
Hinweise
- Fehler nicht ignorieren:Verwenden Sie keine leeren catch-Blöcke, um Fehler abzufangen und zu ignorieren
- Fehlertypen klar angeben:Verwenden Sie nach Möglichkeit spezifische Fehlertypen statt des generischen Error
- Fehlergrenzen:Richten Sie einen einheitlichen Fehlerbehandlungsmechanismus in der Anwendung ein
- Ausnahmen nicht übermäßig verwenden:Bevorzugen Sie bei vorhersehbaren Fehlern Rückgabewerte gegenüber dem Werfen von Ausnahmen
Vorschlag:Wählen Sie einen Fehlerbehandlungsansatz je nach Szenario: Verwenden Sie Ausnahmen für Programmfehler und Result für fachliche Fehler.
Zusammenfassung
Eine gute Fehlerbehandlung ist die Grundlage für den Aufbau robuster Anwendungen.
- Benutzerdefinierte Fehler:Erweitern Sie die Error-Klasse und fügen Sie Informationen wie Fehlercodes hinzu
- Result-Typ:Behandeln Sie Fehler über Rückgabewerte und vermeiden Sie Ausnahmen
- async/await:Verwenden Sie try-catch für asynchrone Fehler
- Fehler-Wrapping:Erstellen Sie allgemeine Fehlerbehandlungsfunktionen
- Fehlergrenzen:Einen einheitlichen Mechanismus zur Fehlerbehandlung einrichten
Best Practice:Wählen Sie je nach konkretem Szenario einen geeigneten Ansatz für die Fehlerbehandlung, der Code-Lesbarkeit und Robustheit in Einklang bringt.
Andere Erweiterungen