Als ich zum ersten Mal auf asynchrones JavaScript stieß, hatte ich Probleme mit Rückrufen und hatte keine Ahnung, wie Promises unter der Haube funktioniert. Mit der Zeit veränderte das Kennenlernen von Promises und Async/Await meine Herangehensweise an das Codieren und machte es viel einfacher zu handhaben. In diesem Blog werden wir diese asynchronen Muster Schritt für Schritt untersuchen und zeigen, wie sie Ihren Entwicklungsprozess rationalisieren und Ihren Code sauberer und effizienter machen können. Lassen Sie uns gemeinsam eintauchen und diese Konzepte entdecken!
Das Erlernen von asynchronem JavaScript ist für die moderne Webentwicklung unerlässlich. Damit können Sie Aufgaben wie API-Anfragen effizient bearbeiten und Ihre Anwendungen reaktionsschnell und schnell halten. Die Beherrschung asynchroner Techniken wie Promises und Async/Await ist nicht nur für die Erstellung skalierbarer Anwendungen von entscheidender Bedeutung, sondern auch für den Erfolg bei JavaScript-Vorstellungsgesprächen, bei denen das Verständnis dieser Konzepte häufig im Mittelpunkt steht. Indem Sie asynchrones JavaScript beherrschen, verbessern Sie Ihre Programmierkenntnisse und bereiten sich besser auf Herausforderungen in der realen Welt vor.
Asynchrone Muster in JavaScript sind Techniken, mit denen Aufgaben erledigt werden, die Zeit in Anspruch nehmen, z. B. das Abrufen von Daten von einem Server, ohne dass die Anwendung einfriert. Ursprünglich verwendeten Entwickler Callbacks, um diese Aufgaben zu verwalten, aber dieser Ansatz führte oft zu komplexem und schwer lesbarem Code, der als „Callback-Hölle“ bekannt ist. Um dies zu vereinfachen, wurden Promises eingeführt, die eine sauberere Möglichkeit zur Handhabung asynchroner Vorgänge bieten, indem Aktionen verkettet und Fehler eleganter behandelt werden. Die Entwicklung wurde mit async/await fortgesetzt, das es Ihnen ermöglicht, asynchronen Code zu schreiben, der eher wie synchroner Code aussieht und sich verhält, wodurch er einfacher zu lesen und zu warten ist. Diese Muster sind entscheidend für die Erstellung effizienter, reaktionsfähiger Anwendungen und von grundlegender Bedeutung für die moderne JavaScript-Entwicklung. Wir werden diese Konzepte in diesem Blog ausführlicher untersuchen.
Rückrufe sind Funktionen, die Sie als Argumente an andere Funktionen übergeben, mit der Absicht, dass die empfangende Funktion den Rückruf irgendwann ausführt. Dies ist nützlich für Szenarien, in denen Sie sicherstellen möchten, dass Code ausgeführt wird, nachdem eine bestimmte Aufgabe abgeschlossen ist, z. B. nach dem Abrufen von Daten von einem Server oder dem Abschluss einer Berechnung.
So funktionieren Rückrufe:
Beispiel 1
function fetchData(callback) { // Simulate fetching data with a delay setTimeout(() => { const data = "Data fetched"; callback(data); // Call the callback function with the fetched data }, 1000); } function processData(data) { console.log("Processing:", data); } fetchData(processData); // fetchData will call processData with the data
Beispiel 2
// Function that adds two numbers and uses a callback to return the result function addNumbers(a, b, callback) { const result = a + b; callback(result); // Call the callback function with the result } // Callback function to handle the result function displayResult(result) { console.log("The result is:", result); } // Call addNumbers with the displayResult callback addNumbers(5, 3, displayResult);
Hinweis: Ich denke, Rückrufe sind effektiv für die Handhabung asynchroner Vorgänge, aber seien Sie vorsichtig: Wenn die Komplexität Ihres Codes zunimmt, insbesondere bei verschachtelten Rückrufen, kann es zu einem Problem kommen, das als „Rückrufhölle“ bekannt ist. Dieses Problem tritt auf, wenn Rückrufe tief ineinander verschachtelt sind, was zu Lesbarkeitsproblemen führt und die Wartung des Codes erschwert.
Callback Hell (auch bekannt als Pyramid of Doom) bezieht sich auf die Situation, in der Sie mehrere verschachtelte Rückrufe haben. Dies geschieht, wenn Sie mehrere asynchrone Vorgänge nacheinander ausführen müssen und jeder Vorgang vom vorherigen abhängt.
Bsp. Dadurch entsteht eine „Pyramidenstruktur“, die schwer zu lesen und aufrechtzuerhalten ist.
fetchData(function(data1) { processData1(data1, function(result1) { processData2(result1, function(result2) { processData3(result2, function(result3) { console.log("Final result:", result3); }); }); }); });
Probleme mit Callback Hell:
Bei der Arbeit mit Rückrufen wird häufig ein Muster verwendet, das als Fehler-zuerst-Rückrufe bekannt ist. In diesem Muster akzeptiert die Rückruffunktion einen Fehler als erstes Argument. Liegt kein Fehler vor, ist das erste Argument normalerweise null oder undefiniert und das tatsächliche Ergebnis wird als zweites Argument bereitgestellt.
function fetchData(callback) { setTimeout(() => { const error = null; // Or `new Error("Some error occurred")` if there's an error const data = "Data fetched"; callback(error, data); // Pass error and data to the callback }, 1000); } function processData(error, data) { if (error) { console.error("Error:", error); return; } console.log("Processing:", data); } fetchData(processData); // `processData` will handle both error and data
Hinweis: Nach Rückrufen wurden Promises eingeführt, um asynchrone Prozesse in JavaScript zu verarbeiten. Wir werden nun tiefer in Promises eintauchen und untersuchen, wie sie unter der Haube funktionieren.
Promises sind Objekte, die den eventuellen Abschluss (oder Misserfolg) eines asynchronen Vorgangs und den daraus resultierenden Wert darstellen. Sie bieten eine sauberere Möglichkeit, asynchronen Code im Vergleich zu Rückrufen zu verarbeiten.
Zweck der Versprechen:
A Promise can be in one of three states:
Note: If you want to explore more, you should check out Understand How Promises Work Under the Hood where I discuss how promises work under the hood.
example 1
// Creating a new promise const myPromise = new Promise((resolve, reject) => { const success = true; // Simulate success or failure if (success) { resolve("Operation successful!"); // If successful, call resolve } else { reject("Operation failed!"); // If failed, call reject } }); // Using the promise myPromise .then((message) => { console.log(message); // Handle the successful case }) .catch((error) => { console.error(error); // Handle the error case });
example 2
const examplePromise = new Promise((resolve, reject) => { setTimeout(() => { const success = Math.random() > 0.5; // Randomly succeed or fail if (success) { resolve("Success!"); } else { reject("Failure."); } }, 1000); }); console.log("Promise state: Pending..."); // To check the state, you would use `.then()` or `.catch()` examplePromise .then((message) => { console.log("Promise state: Fulfilled"); console.log(message); }) .catch((error) => { console.log("Promise state: Rejected"); console.error(error); });
Chaining allows you to perform multiple asynchronous operations in sequence, with each step depending on the result of the previous one.
Chaining promises is a powerful feature of JavaScript that allows you to perform a sequence of asynchronous operations where each step depends on the result of the previous one. This approach is much cleaner and more readable compared to deeply nested callbacks.
Promise chaining involves connecting multiple promises in a sequence. Each promise in the chain executes only after the previous promise is resolved, and the result of each promise can be passed to the next step in the chain.
function step1() { return new Promise((resolve) => { setTimeout(() => resolve("Step 1 completed"), 1000); }); } function step2(message) { return new Promise((resolve) => { setTimeout(() => resolve(message + " -> Step 2 completed"), 1000); }); } function step3(message) { return new Promise((resolve) => { setTimeout(() => resolve(message + " -> Step 3 completed"), 1000); }); } // Chaining the promises step1() .then(result => step2(result)) .then(result => step3(result)) .then(finalResult => console.log(finalResult)) .catch(error => console.error("Error:", error));
Disadvantages of Chaining:
While chaining promises improves readability compared to nested callbacks, it can still become unwieldy if the chain becomes too long or complex. This can lead to readability issues similar to those seen with callback hell.
Note: To address these challenges, async and await were introduced to provide an even more readable and straightforward way to handle asynchronous operations in JavaScript.
async and await are keywords introduced in JavaScript to make handling asynchronous code more readable and easier to work with.
async function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve("Data fetched"); }, 1000); }); } async function getData() { const data = await fetchData(); // Wait for fetchData to resolve console.log(data); // Logs "Data fetched" } getData();
1. Async Functions Always Return a Promise:
No matter what you return from an async function, it will always be wrapped in a promise. For example:
async function example() { return "Hello"; } example().then(console.log); // Logs "Hello"
Even though example() returns a string, it is automatically wrapped in a promise.
2. Await Pauses Execution:
The await keyword pauses the execution of an async function until the promise it is waiting for resolves.
async function example() { console.log("Start"); const result = await new Promise((resolve) => { setTimeout(() => { resolve("Done"); }, 1000); }); console.log(result); // Logs "Done" after 1 second } example();
In this example:
Handling errors with async/await is done using try/catch blocks, which makes error handling more intuitive compared to promise chains.
async function fetchData() { throw new Error("Something went wrong!"); } async function getData() { try { const data = await fetchData(); console.log(data); } catch (error) { console.error("Error:", error.message); // Logs "Error: Something went wrong!" } } getData();
With Promises, you handle errors using .catch():
fetchData() .then(data => console.log(data)) .catch(error => console.error("Error:", error.message));
Using async/await with try/catch often results in cleaner and more readable code.
You can use async/await with existing promise-based functions seamlessly.
example
function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve("Data fetched"); }, 1000); }); } async function getData() { const data = await fetchData(); // Wait for the promise to resolve console.log(data); // Logs "Data fetched" } getData();
Best Practices:
Async und Wait bieten eine sauberere und besser lesbare Möglichkeit, asynchrone Vorgänge im Vergleich zu herkömmlicher Versprechensverkettung und Rückrufen abzuwickeln. Indem sie Ihnen ermöglichen, asynchronen Code zu schreiben, der wie synchroner Code aussieht und sich verhält, vereinfachen sie komplexe Logik und verbessern die Fehlerbehandlung mit Try/Catch-Blöcken. Die Verwendung von async/await mit Versprechen führt zu wartbarerem und verständlicherem Code.
Das obige ist der detaillierte Inhalt vonBeherrschen von JavaScript-Async-Mustern: Von Rückrufen zu Async/Await. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!