Asynchrone Programmierung ist ein Programmierparadigma, das es Ihnen ermöglicht, Code zu schreiben, der asynchron
ausgeführt wird. Im Gegensatz zur synchronen Programmierung, die Code sequenziell ausführt, erlaubt die asynchrone Programmierung, dass Code im Hintergrund läuft, während der Rest des Programms weiterhin ausgeführt wird. Dies ist besonders nützlich für Aufgaben, die lange dauern können, wie das Abrufen von Daten von einer entfernten API.
Asynchrone Programmierung
ist entscheidend für die Erstellung reaktionsfähiger und effizienter Anwendungen in JavaScript. TypeScript, ein Superset von JavaScript, erleichtert die Arbeit mit asynchroner Programmierung noch weiter.
Es gibt mehrere Ansätze zur asynchronen Programmierung
in TypeScript, einschließlich der Verwendung von Promises
, async/await
und Callbacks
. Wir werden jeden dieser Ansätze im Detail behandeln, damit Sie die besten für Ihren Anwendungsfall auswählen können.
Inhaltsverzeichnis
Warum ist asynchrone Programmierung wichtig?
Asynchrone Programmierung ist entscheidend für den Aufbau reaktionsfähiger und effizienter Webanwendungen. Sie ermöglicht es, Aufgaben im Hintergrund auszuführen, während der Rest des Programms fortgesetzt wird, wodurch die Benutzeroberfläche auf Eingaben reagiert bleibt. Außerdem kann asynchrone Programmierung die Gesamtleistung steigern, indem mehrere Aufgaben gleichzeitig ausgeführt werden können.
Es gibt viele Beispiele aus der realen Welt für asynchrone Programmierung, wie den Zugriff auf Benutzerkameras und -mikrofone sowie die Verarbeitung von Benutzereingaben. Selbst wenn Sie nicht häufig asynchrone Funktionen erstellen, ist es wichtig zu wissen, wie man sie korrekt verwendet, um sicherzustellen, dass Ihre Anwendung zuverlässig ist und gut funktioniert.
Wie TypeScript die asynchrone Programmierung erleichtert
TypeScript bietet mehrere Funktionen, die die asynchrone Programmierung vereinfachen, darunter Typsicherheit
, Typinferenz
, Typüberprüfung
und Typannotationen
.
Mit der Typsicherheit können Sie sicherstellen, dass Ihr Code wie erwartet funktioniert, selbst bei der Arbeit mit asynchronen Funktionen. Zum Beispiel kann TypeScript Fehler im Zusammenhang mit null- und undefined-Werten bereits zur Kompilierzeit erkennen und Ihnen so Zeit und Aufwand bei der Fehlersuche ersparen.
Die Typinferenz und -überprüfung von TypeScript reduzieren auch die Menge an Standardcode, den Sie schreiben müssen, was Ihren Code prägnanter und leichter lesbar macht.
Und die Typannotationen von TypeScript sorgen für Klarheit und Dokumentation Ihres Codes, was besonders hilfreich ist, wenn Sie mit asynchronen Funktionen arbeiten, die komplex zu verstehen sein können.
Lassen Sie uns nun eintauchen und mehr über diese drei Schlüsselfunktionen der asynchronen Programmierung erfahren: Versprechen, async/await und Rückrufe.
Verwendung von Versprechen in TypeScript
Versprechen sind ein leistungsstolles Werkzeug zum Umgang mit asynchronen Operationen in TypeScript. Beispielsweise könnten Sie ein Versprechen verwenden, um Daten von einer externen API abzurufen oder eine zeitaufwändige Aufgabe im Hintergrund auszuführen, während Ihr Hauptthread weiterläuft.
Um ein Versprechen zu verwenden, erstellen Sie eine neue Instanz der Promise
-Klasse und übergeben ihr eine Funktion, die die asynchrone Operation durchführt. Diese Funktion sollte die resolve-Methode mit dem Ergebnis aufrufen, wenn die Operation erfolgreich ist, oder die reject-Methode mit einem Fehler, wenn sie fehlschlägt.
Nachdem das Versprechen erstellt wurde, können Sie Rückrufe daran anhängen, indem Sie die then
-Methode verwenden. Diese Rückrufe werden ausgelöst, wenn das Versprechen erfüllt ist, und der aufgelöste Wert wird als Parameter übergeben. Wenn das Versprechen abgelehnt wird, können Sie einen Fehlerbehandler mit der catch-Methode anhängen, der mit dem Grund für die Ablehnung aufgerufen wird.
Die Verwendung von Versprechen bietet mehrere Vorteile gegenüber traditionellen rückrufbasierten Methoden. Zum Beispiel können Versprechen helfen, „Callback-Hölle“ zu vermeiden, ein häufiges Problem in asynchronem Code, bei dem verschachtelte Rückrufe schwer zu lesen und zu pflegen sind.
Versprechen erleichtern auch die Fehlerbehandlung in asynchronem Code, da Sie die catch-Methode verwenden können, um Fehler zu verwalten, die überall in der Versprechenkette auftreten.
Abschließend können Versprechen Ihren Code vereinfachen, indem sie einen konsistenten, zusammensetzbaren Weg bieten, um asynchrone Operationen unabhängig von ihrer zugrunde liegenden Implementierung zu behandeln.
Wie man ein Promise erstellt
Promise-Syntax:
const myPromise = new Promise((resolve, reject) => {
// Führe eine asynchrone Operation aus
// Wenn die Operation erfolgreich ist, rufe resolve mit dem Ergebnis auf
// Wenn die Operation fehlschlägt, rufe reject mit einem Fehlerobjekt auf
});
myPromise
.then((result) => {
// Verarbeite das erfolgreiche Ergebnis
})
.catch((error) => {
// Verarbeite den Fehler
});
// Beispiel 1, wie man ein Promise erstellt
function myAsyncFunction(): Promise<string> {
return new Promise<string>((resolve, reject) => {
// Einige asynchrone Operation
setTimeout(() => {
// Erfolgreiche Operation löst das Promise aus. Schau dir meinen neuesten Blogbeitrag über das Meistern von asynchroner Programmierung in TypeScript an! Lerne, wie man mit Promises, Async/Await und Callbacks arbeitet, um effizienten und skalierbaren Code zu schreiben. Mach dich bereit, deine TypeScript-Fähigkeiten auf die nächste Stufe zu heben!
const success = true;
if (success) {
// Löse das Promise mit dem Ergebnisergebnis, wenn die Operation erfolgreich war
resolve(
`The result is success and your operation result is ${operationResult}`
);
} else {
const rejectCode: number = 404;
const rejectMessage: string = `The result is failed and your operation result is ${rejectCode}`;
// Lehne das Promise mit dem Ergebnisergebnis ab, wenn die Operation fehlgeschlagen ist
reject(new Error(rejectMessage));
}
}, 2000);
});
}
// Verwende das Promise
myAsyncFunction()
.then((result) => {
console.log(result); // Ausgabe: Das Ergebnis ist Erfolg und dein Operationsergebnis ist 4
})
.catch((error) => {
console.error(error); // Ausgabe: Das Ergebnis ist fehlgeschlagen und dein Operationsergebnis ist 404
});
Im obigen Beispiel haben wir eine Funktion namens myAsyncFunction()
, die ein Promise
zurückgibt. Wir verwenden den Promise
-Konstruktor, um das Versprechen zu erstellen, der eine Callback-Funktion
mit den Argumenten resolve
und reject
verwendet. Wenn die asynchrone Operation erfolgreich ist, rufen wir die resolve-Funktion auf. Wenn sie scheitert, rufen wir die reject-Funktion auf.
Das durch den Konstruktor zurückgegebene Promise-Objekt verfügt über eine Methode namens then()
, die Erfolgs- und Fehler-Callback-Funktionen annimmt. Wenn das Promise erfolgreich aufgelöst wird, wird die Erfolgs-Callback-Funktion mit dem Ergebnis aufgerufen. Wenn das Promise abgelehnt wird, wird die Fehler-Callback-Funktion mit einer Fehlermeldung aufgerufen.
Das Promise-Objekt verfügt auch über eine Methode namens catch()
, die verwendet wird, um Fehler zu behandeln, die während der Promise-Kette auftreten. Die catch()
-Methode nimmt eine Callback-Funktion an, die aufgerufen wird, wenn ein Fehler in der Promise-Kette auftritt.
Jetzt gehen wir dazu über, wie man Promises in TypeScript verkettet.
Wie man Promises verkettet
Das Verketten von Promises ermöglicht es Ihnen, mehrere asynchrone Operationen
in Sequenz oder parallel auszuführen. Dies ist hilfreich, wenn Sie mehrere asynchrone Aufgaben nacheinander oder gleichzeitig ausführen müssen. Zum Beispiel müssen Sie möglicherweise Daten asynchron abrufen und sie dann asynchron verarbeiten.
Lassen Sie uns ein Beispiel anschauen, wie man Promises verkettet:
// Beispiel, wie das Verketten von Versprechen funktioniert
// Erstes Versprechen
const promise1 = new Promise((resolve, reject) => {
const functionOne: string = "This is the first promise function";
setTimeout(() => {
resolve(functionOne);
}, 1000);
});
// Zweites Versprechen
const promise2 = (data: number) => {
const functionTwo: string = "This is the second second promise function";
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(` ${data} '+' ${functionTwo} `);
}, 1000);
});
};
// Verketten des ersten und zweiten Versprechens
promise1
.then(promise2)
.then((result) => {
console.log(result); // Ausgabe: Dies ist die erste Versprechenfunktion + Dies ist die zweite Versprechenfunktion
})
.catch((error) => {
console.error(error);
});
Im obigen Beispiel haben wir zwei Versprechen: promise1
und promise2
. promise1
wird nach 1 Sekunde mit dem String „Dies ist die erste Versprechenfunktion.“ aufgelöst. promise2
nimmt eine Zahl als Eingabe und gibt ein Versprechen zurück, das nach 1 Sekunde mit einem String aufgelöst wird, der die Eingabezahl und den String „Dies ist die zweite Versprechenfunktion.“ kombiniert.
Wir verketten die beiden Versprechen mit der then
Methode. Die Ausgabe von promise1
wird als Eingabe an promise2
übergeben. Schließlich verwenden wir erneut die then
Methode, um die Ausgabe von promise2
in der Konsole zu protokollieren. Wenn eines der Versprechen, promise1
oder promise2
, fehlschlägt, wird der Fehler mit der catch
Methode abgefangen.
Herzlichen Glückwunsch! Sie haben gelernt, wie man Versprechen in TypeScript erstellt und verketten kann. Sie können jetzt Versprechen verwenden, um asynchrone Operationen in TypeScript durchzuführen. Jetzt lassen Sie uns erkunden, wie Async/Await
in TypeScript funktioniert.
Wie man Async / Await in TypeScript verwendet
Async/await ist eine Syntax, die in ES2017 eingeführt wurde, um die Arbeit mit Promises zu erleichtern. Sie ermöglicht es, asynchronen Code zu schreiben, der aussieht und sich anfühlt wie synchroner Code.
In TypeScript kannst du eine asynchrone Funktion mit dem async
-Schlüsselwort definieren. Dies teilt dem Compiler mit, dass die Funktion asynchron ist und ein Promise zurückgibt.
Jetzt sehen wir uns an, wie man async/await in TypeScript verwendet.
Async / Await Syntax:
// Async / Await Syntax in TypeScript
async function functionName(): Promise<ReturnType> {
try {
const result = await promise;
// Code, der nach der Auflösung des Promises ausgeführt wird
return result;
} catch (error) {
// Code, der ausgeführt wird, wenn das Promise abgelehnt wird
throw error;
}
}
Im obigen Beispiel ist functionName
eine asynchrone Funktion, die ein Promise von ReturnType
zurückgibt. Das await
-Schlüsselwort wird verwendet, um auf die Auflösung des Promises zu warten, bevor zur nächsten Codezeile übergegangen wird.
Der try/catch
-Block wird verwendet, um Fehler zu behandeln, die beim Ausführen des Codes innerhalb der asynchronen Funktion auftreten. Wenn ein Fehler auftritt, wird er vom Catch-Block erfasst, wo du ihn angemessen behandeln kannst.
Verwendung von Pfeilfunktionen mit Async / Await
Du kannst auch Pfeilfunktionen mit der Async/Await-Syntax in TypeScript verwenden:
const functionName = async (): Promise<ReturnType> => {
try {
const result = await promise;
// Code, der nach der Auflösung des Promises ausgeführt wird
return result;
} catch (error) {
// Code, der ausgeführt wird, wenn das Promise abgelehnt wird
throw error;
}
};
Im obigen Beispiel ist functionName
als Pfeilfunktion definiert, die ein Promise von ReturnType
zurückgibt. Das async-Schlüsselwort gibt an, dass es sich um eine asynchrone Funktion handelt, und das await-Schlüsselwort wird verwendet, um auf die Auflösung des Versprechens zu warten, bevor zur nächsten Codezeile übergegangen wird.
Async/Await mit einem API-Aufruf
Jetzt gehen wir über die Syntax hinaus und rufen einige Daten aus einer API mit async/await ab.
interface User {
id: number;
name: string;
email: string;
}
const fetchApi = async (): Promise<void> => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
if (!response.ok) {
throw new Error(
`Failed to fetch users (HTTP status code: ${response.status})`
);
}
const data: User[] = await response.json();
console.log(data);
} catch (error) {
console.error(error);
throw error;
}
};
fetchApi();
Hier rufen wir Daten von der JSONPlaceholder-API ab, konvertieren sie in JSON und geben sie dann in der Konsole aus. Dies ist ein Beispiel aus der Praxis, wie man async/await in TypeScript verwendet.
Sie sollten Benutzerinformationen in der Konsole sehen. Dieses Bild zeigt die Ausgabe:
Async/Await mit Axios-API-Aufruf
// Beispiel 2 zur Verwendung von async/await in TypeScript
const fetchApi = async (): Promise<void> => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/users"
);
const data = await response.data;
console.log(data);
} catch (error) {
console.error(error);
}
};
fetchApi();
Im obigen Beispiel definieren wir die Funktion fetchApi()
unter Verwendung von async/await und der Methode Axios.get()
zum Senden einer HTTP-GET-Anfrage an die angegebene URL. Wir verwenden await, um auf die Antwort zu warten, extrahieren dann die Daten mithilfe der data-Eigenschaft des Antwortobjekts. Schließlich geben wir die Daten mit console.log()
in der Konsole aus. Auftretende Fehler werden eingefangen und mit console.error()
in der Konsole protokolliert.
Wir können dies mit Axios erreichen, sodass Sie das gleiche Ergebnis in der Konsole sehen sollten.
Dieses Bild zeigt die Ausgabe bei Verwendung von Axios in der Konsole:
Hinweis: Bevor Sie den obigen Code ausprobieren, müssen Sie Axios mithilfe von npm oder yarn installieren.
npm install axios
yarn add axios
Wenn Sie nicht vertraut sind mit Axios, können Sie hier mehr darüber erfahren.
Sie können sehen, dass wir einen try
und catch
Block verwendet haben, um Fehler zu behandeln. Der try
und catch
Block ist eine Methode zur Verwaltung von Fehlern in TypeScript. Also, immer wenn Sie API-Aufrufe machen wie gerade eben, stellen Sie sicher, dass Sie einen try
und catch
Block verwenden, um Fehler zu behandeln.
Jetzt wollen wir eine fortgeschrittenere Verwendung des try
und catch
Blocks in TypeScript erkunden:
// Beispiel 3, wie man async / await in TypeScript verwendet
interface Recipe {
id: number;
name: string;
ingredients: string[];
instructions: string[];
prepTimeMinutes: number;
cookTimeMinutes: number;
servings: number;
difficulty: string;
cuisine: string;
caloriesPerServing: number;
tags: string[];
userId: number;
image: string;
rating: number;
reviewCount: number;
mealType: string[];
}
const fetchRecipes = async (): Promise<Recipe[] | string> => {
const api = "https://dummyjson.com/recipes";
try {
const response = await fetch(api);
if (!response.ok) {
throw new Error(`Failed to fetch recipes: ${response.statusText}`);
}
const { recipes } = await response.json();
return recipes; // Gib das Rezepte-Array zurück
} catch (error) {
console.error("Error fetching recipes:", error);
if (error instanceof Error) {
return error.message;
}
return "An unknown error occurred.";
}
};
// Rezepte abrufen und protokollieren
fetchRecipes().then((data) => {
if (Array.isArray(data)) {
console.log("Recipes fetched successfully:", data);
} else {
console.error("Error message:", data);
}
});
In dem obigen Beispiel definieren wir ein interface Recipe
, das die Struktur der Daten, die wir von der API erwarten, umreißt. Wir erstellen dann die Funktion fetchRecipes()
unter Verwendung von async/await und der fetch() Methode, um eine HTTP GET-Anfrage an den spezifizierten API-Endpunkt zu senden.
Wir verwenden einen try/catch
Block, um Fehler zu behandeln, die während der API-Anfrage auftreten könnten. Wenn die Anfrage erfolgreich ist, extrahieren wir die Daten aus der Antwort unter Verwendung von await und geben sie zurück. Wenn ein Fehler auftritt, überprüfen wir eine Fehlermeldung und geben sie als Zeichenfolge zurück, wenn sie vorhanden ist.
Zuletzt rufen wir die Funktion fetchRecipes()
auf und verwenden .then()
, um die zurückgegebenen Daten in der Konsole auszugeben. Dieses Beispiel zeigt, wie man async/await
mit try/catch
-Blöcken verwendet, um Fehler in einem fortgeschritteneren Szenario zu behandeln, in dem wir Daten aus einem Antwortobjekt extrahieren müssen und eine benutzerdefinierte Fehlermeldung zurückgeben müssen.
Dieses Bild zeigt das Ausgabenergebnis des Codes:
Async / Await mit Promise.all
Promise.all()
ist eine Methode, die ein Array von Versprechen als Eingabe (eine Iteration) annimmt und ein einzelnes Versprechen als Ausgabe zurückgibt. Dieses Versprechen wird erfüllt, wenn alle Eingabeversprechen erfüllt wurden oder wenn die Eingabeiteration keine Versprechen enthält. Es wird sofort abgelehnt, wenn eines der Eingabeversprechen abgelehnt wird oder wenn Nicht-Versprechen einen Fehler werfen, und es wird mit der ersten Ablehnungsnachricht oder dem Fehler abgelehnt.
// Beispiel zur Verwendung von async/await mit Promise.all
interface User {
id: number;
name: string;
email: string;
profilePicture: string;
}
interface Post {
id: number;
title: string;
body: string;
}
interface Comment {
id: number;
postId: number;
name: string;
email: string;
body: string;
}
const fetchApi = async <T>(url: string): Promise<T> => {
try {
const response = await fetch(url);
if (response.ok) {
const data = await response.json();
return data;
} else {
throw new Error(`Network response was not ok for ${url}`);
}
} catch (error) {
console.error(error);
throw new Error(`Error fetching data from ${url}`);
}
};
const fetchAllApis = async (): Promise<[User[], Post[], Comment[]]> => {
try {
const [users, posts, comments] = await Promise.all([
fetchApi<User[]>("https://jsonplaceholder.typicode.com/users"),
fetchApi<Post[]>("https://jsonplaceholder.typicode.com/posts"),
fetchApi<Comment[]>("https://jsonplaceholder.typicode.com/comments"),
]);
return [users, posts, comments];
} catch (error) {
console.error(error);
throw new Error("Error fetching data from one or more APIs");
}
};
fetchAllApis()
.then(([users, posts, comments]) => {
console.log("Users: ", users);
console.log("Posts: ", posts);
console.log("Comments: ", comments);
})
.catch((error) => console.error(error));
Im obigen Code haben wir Promise.all
verwendet, um mehrere APIs gleichzeitig abzurufen. Wenn Sie mehrere APIs abrufen müssen, können Sie Promise.all
verwenden, um sie alle auf einmal zu erhalten. Wie Sie sehen können, haben wir map
verwendet, um durch das Array von APIs zu iterieren und sie dann an Promise.all
zu übergeben, um sie gleichzeitig abzurufen.
Das folgende Bild zeigt die Ausgabe der API-Aufrufe:
Lassen Sie uns sehen, wie man Promise.all
mit Axios verwendet:
// Beispiel zur Verwendung von async/await mit Axios und Promise.all
const fetchApi = async () => {
try {
const urls = [
"https://jsonplaceholder.typicode.com/users",
"https://jsonplaceholder.typicode.com/posts",
];
const responses = await Promise.all(urls.map((url) => axios.get(url)));
const data = await Promise.all(responses.map((response) => response.data));
console.log(data);
} catch (error) {
console.error(error);
}
};
fetchApi();
Im obigen Beispiel verwenden wir Promise.all
, um Daten gleichzeitig von zwei verschiedenen URLs abzurufen. Zuerst erstellen wir ein Array von URLs, dann verwenden wir die Map, um ein Array von Promises aus den axios.get
-Aufrufen zu erstellen. Wir übergeben dieses Array an Promise.all
, das ein Array von Antworten zurückgibt. Schließlich verwenden wir die Map erneut, um die Daten aus jeder Antwort zu extrahieren und sie in der Konsole auszugeben.
Wie man Callbacks in TypeScript verwendet
Ein Callback ist eine Funktion, die als Argument an eine andere Funktion übergeben wird. Die Callback-Funktion wird innerhalb der anderen Funktion ausgeführt. Callbacks stellen sicher, dass eine Funktion nicht ausgeführt wird, bevor eine Aufgabe abgeschlossen ist – aber dass sie dann direkt nach dem Abschluss der Aufgabe ausgeführt wird. Sie helfen uns, asynchronen JavaScript-Code zu schreiben und Probleme und Fehler zu vermeiden.
// Beispiel für die Verwendung von Callbacks in TypeScript
const add = (a: number, b: number, callback: (result: number) => void) => {
const result = a + b;
callback(result);
};
add(10, 20, (result) => {
console.log(result);
});
Das Bild unten zeigt die Callback-Funktion:
Schauen wir uns ein weiteres Beispiel für die Verwendung von Callbacks in TypeScript an:
// Beispiel für die Verwendung einer Callback-Funktion in TypeScript
type User = {
name: string;
email: string;
};
const fetchUserData = (
id: number,
callback: (error: Error | null, user: User | null) => void
) => {
const api = `https://jsonplaceholder.typicode.com/users/${id}`;
fetch(api)
.then((response) => {
if (response.ok) {
return response.json();
} else {
throw new Error("Network response was not ok.");
}
})
.then((data) => {
const user: User = {
name: data.name,
email: data.email,
};
callback(null, user);
})
.catch((error) => {
callback(error, null);
});
};
// Verwendung von fetchUserData mit einer Callback-Funktion
fetchUserData(1, (error, user) => {
if (error) {
console.error(error);
} else {
console.log(user);
}
});
Im obigen Beispiel haben wir eine Funktion namens fetchUserData
, die eine id
und ein Callback
als Parameter entgegennimmt. Dieses Callback
ist eine Funktion mit zwei Parametern: einem Fehler und einem Benutzer.
Die fetchUserData
-Funktion ruft Benutzerdaten von einem JSONPlaceholder-API-Endpunkt unter Verwendung der id
ab. Wenn der Abruf erfolgreich ist, wird ein User
-Objekt erstellt und mit einem null Fehler an die Callback-Funktion übergeben. Wenn während des Abrufs ein Fehler auftritt, wird der Fehler mit einem null Benutzer an die Callback-Funktion gesendet.
Um die fetchUserData
-Funktion mit einem Callback zu verwenden, geben wir eine id
und eine Callback-Funktion als Argumente an. Die Callback-Funktion prüft auf Fehler und protokolliert die Benutzerdaten, wenn keine Fehler vorliegen.
Das Bild unten zeigt die Ausgabe der API-Aufrufe:
Wie man Callbacks verantwortungsbewusst verwendet
Während Callbacks grundlegend für asynchrones Programmieren in TypeScript sind, erfordern sie eine sorgfältige Verwaltung, um „Callback-Hölle“ – den pyramidenförmigen, tief verschachtelten Code, der schwer zu lesen und zu warten ist – zu vermeiden. Hier ist, wie man Callbacks effektiv nutzt:
-
Vermeiden Sie tiefe Verschachtelung
-
Flachen Sie Ihre Code-Struktur, indem Sie komplexe Operationen in benannte Funktionen aufteilen
-
Verwenden Sie Promises oder async/await für komplexe asynchrone Workflows (mehr dazu unten)
-
-
Fehlerbehandlung zuerst
-
Folgen Sie immer der Node.js-Konvention von
(Fehler, Ergebnis)
Parametern -
Überprüfen Sie Fehler auf jeder Ebene verschachtelter Callbacks
-
function processData(input: string, callback: (err: Error | null, result?: string) => void) {
// ... rufen Sie immer zuerst das Callback mit dem Fehler auf
}
-
Verwenden Sie Typannotationen
-
Nutzen Sie das Typsystem von TypeScript, um Callback-Signaturen durchzusetzen
-
Definieren Sie klare Schnittstellen für Callback-Parameter
-
type ApiCallback = (error: Error | null, data?: ApiResponse) => void;
-
Erwägen Sie Kontrollflussbibliotheken
Für komplexe asynchrone Operationen verwenden Sie Hilfsprogramme wieasync.js
für:-
Parallele Ausführung
-
Reihenfolge der Ausführung
-
Fehlerbehandlungspipelines
-
Wann man Callbacks vs. Alternativen verwenden sollte
Es gibt Zeiten, in denen Callbacks eine gute Wahl sind, und andere Zeiten, in denen sie es nicht sind.
Callbacks sind hilfreich, wenn Sie mit asynchronen Operationen arbeiten (einzeln abgeschlossen), mit älteren Bibliotheken oder APIs zusammenarbeiten, die Callbacks erwarten, Ereignislistener behandeln (wie Klick-Listener oder Websocket-Ereignisse) oder leichtgewichtige Hilfsprogramme mit einfachen asynchronen Anforderungen erstellen.
In anderen Szenarien, in denen Sie sich auf das Schreiben wartbarer Code mit einem klaren asynchronen Fluss konzentrieren müssen, verursachen Callbacks Probleme und Sie sollten Promises oder async-await bevorzugen. Zum Beispiel, wenn Sie mehrere Operationen verketten, komplexe Fehlerpropagation handhaben, mit modernen APIs arbeiten (wie der Fetch-API oder FS Promises) oder promise.all()
für parallele Ausführung verwenden müssen.
Beispielhafte Migration von Callbacks zu Promises:
// Rückrufversion
function fetchUser(id: number, callback: (err: Error | null, user?: User) => void) {
// ...
}
// Promise-Version
async function fetchUserAsync(id: number): Promise<User> {
// ...
}
// Verwendung mit async/await
try {
const user = await fetchUserAsync(1);
} catch (error) {
// Fehlerbehandlung
}
Die Evolution der Async-Muster
Muster | Profis | Nachteile |
Rückrufe | Einfach, universell | Verschachtelte Komplexität |
Versprechen | Kettenfähig, bessere Fehlerfluss | Erfordert .then() Ketten |
Async/Await | Sync-ähnliche Lesbarkeit | Erfordert Transpilierung |
Moderner TypeScript-Projekte verwenden oft eine Mischung: Rückrufe für ereignisgesteuerte Muster und Versprechen/async-await für komplexe Async-Logik. Der Schlüssel ist die Auswahl des richtigen Werkzeugs für Ihren spezifischen Anwendungsfall und die Aufrechterhaltung der Codeklarheit.
Fazit
In diesem Artikel haben wir verschiedene Möglichkeiten kennengelernt, asynchronen Code in TypeScript zu behandeln. Wir haben über Rückrufe, Versprechen, async/await und deren Verwendung in TypeScript gelernt. Wir haben auch dieses Konzept kennengelernt.
Wenn Sie mehr über das Programmieren und das Werden eines besseren Software-Ingenieurs erfahren möchten, können Sie meinen YouTube-Kanal CliffTech abonnieren.
Vielen Dank, dass Sie meinen Artikel gelesen haben. Ich hoffe, er hat Ihnen gefallen. Wenn Sie Fragen haben, zögern Sie nicht, mich zu kontaktieren.
Verbinden Sie sich mit mir in den sozialen Medien: