Heim > Web-Frontend > js-Tutorial > Hauptteil

Beherrschen von JavaScript-Async-Mustern: Von Rückrufen zu Async/Await

Patricia Arquette
Freigeben: 2024-09-13 20:16:39
Original
486 Leute haben es durchsucht

Mastering JavaScript Async Patterns: From Callbacks to Async/Await

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!

Warum müssen Sie asynchrones JavaScript lernen?

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.

Was sind asynchrone Muster?

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.

Was ist ein Rückruf?

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:

  1. Sie definieren eine Funktion (Callback).
  2. Sie übergeben diese Funktion als Argument an eine andere Funktion.
  3. Die Empfangsfunktion führt den Rückruf zum entsprechenden Zeitpunkt aus.

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

Nach dem Login kopieren

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

Nach dem Login kopieren

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.

Rückruf Hölle

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);
      });
    });
  });
});

Nach dem Login kopieren

Probleme mit Callback Hell:

  1. Lesbarkeit:Der Code wird schwer zu lesen und zu verstehen.
  2. Wartbarkeit: Das Vornehmen von Änderungen oder das Debuggen wird zu einer Herausforderung.
  3. Fehlerbehandlung:Die Fehlerverwaltung kann kompliziert werden.

Umgang mit Fehlern mit Rückrufen

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

Nach dem Login kopieren

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.

Einführung in Versprechen

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:

  1. Avoid Callback Hell: Promises help manage multiple asynchronous operations without deep nesting.
  2. Improve Readability: Promises provide a more readable way to handle sequences of asynchronous tasks.

Promise States

A Promise can be in one of three states:

  1. Pending: The initial state, before the promise has been resolved or rejected.
  2. Fulfilled: The state when the operation completes successfully, and resolve has been called.
  3. Rejected: The state when the operation fails, and reject has been called.

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
  });

Nach dem Login kopieren

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);
  });

Nach dem Login kopieren

Chaining Promises

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.

How Promise Chaining Works

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

Nach dem Login kopieren

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.

Introduction to Async/Await

async and await are keywords introduced in JavaScript to make handling asynchronous code more readable and easier to work with.

  • async: Marks a function as asynchronous. An async function always returns a promise, and it allows the use of await within it.
  • await: Pauses the execution of the async function until the promise resolves, making it easier to work with asynchronous results in a synchronous-like fashion.
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();

Nach dem Login kopieren

How Async/Await Works

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"

Nach dem Login kopieren

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

Nach dem Login kopieren

In this example:

  • "Start" is logged immediately.
  • The await pauses execution until the promise resolves after 1 second.
  • "Done" is logged after the promise resolves.

Error Handling with Async/Await

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

Nach dem Login kopieren

With Promises, you handle errors using .catch():

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error("Error:", error.message));

Nach dem Login kopieren

Using async/await with try/catch often results in cleaner and more readable code.

Combining Async/Await with Promises

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

Nach dem Login kopieren

Best Practices:

  1. Verwenden Sie async/await für bessere Lesbarkeit: Bei der Arbeit mit mehreren asynchronen Vorgängen kann async/await den Code linearer und leichter verständlich machen.
  2. Mit Promises kombinieren:Verwenden Sie async/await weiterhin mit Promise-basierten Funktionen, um komplexe asynchrone Abläufe natürlicher zu handhaben.
  3. Fehlerbehandlung:Verwenden Sie in asynchronen Funktionen immer Try/Catch-Blöcke, um potenzielle Fehler zu behandeln.

Abschluss

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage