In diesem Artikel untersuchen wir, warum async/await das bevorzugte Tool jedes Javascript-Entwicklers für die asynchrone Programmierung ist. Wenn Sie mit JavaScript noch nicht vertraut sind, machen Sie sich keine Sorgen. Dieser Artikel hilft Ihnen dabei, Async/Await von Grund auf zu verstehen. einführenAsync/await ist ein Muster in JavaScript, das die synchrone Ausführung Ihres Codes ermöglicht, ohne das asynchrone Verhalten von JavaScript zu beeinträchtigen. Definieren asynchroner FunktionenUm eine asynchrone Funktion zu definieren, müssen Sie lediglich vor der Funktionsdefinition ein Schlüsselwort „async“ hinzufügen. // Die asynchrone Funktion gibt immer ein Versprechen zurück asynchrone Funktion greet() { gib "hallo" zurück; } Entspannen Sie sich und machen Sie es sich bequem! 😎. Verwenden Sie das Schlüsselwort „async“ vor dem Funktionsnamen. Sorgen Sie dafür, dass die Funktion ein Versprechen zurückgibt. Wird analysiert, wenn die Funktion zurückkehrt. Endgültige Ablehnung, wenn ein Fehler auftritt. Dies bedeutet, dass Sie nicht jedes Mal „return Promise.new()“ deklarieren müssen, wenn Sie ein Promise erstellen möchten. Um zu zeigen, dass die asynchrone Funktion ein Promise zurückgibt, können wir schnell einen Then-Block anhängen, um dessen Wert auszudrucken. asynchrone Funktion greet() { returniere „Hallo von einer asynchronen Funktion“ } greet().then(Nachricht => console.log(Nachricht)); //Hallo von einer asynchronen Funktion Verwenden von „await“ und Ausführen asynchroner FunktionenIst es nicht cool, dass wir then() und catch() in einer asynchronen Funktion ausführen können? Dies ist jedoch nicht die wirkliche Funktionalität asynchroner Funktionen. Das wahre Potenzial der Funktionen liegt in der „await“-Anweisung. „await“ bewirkt, dass eine Funktion synchron ausgeführt wird, während die Kontrolle in dieser Zeile gehalten wird, bis die erwartete Methode ihre Ausführung abgeschlossen hat. asynchrone Funktion greet() { returniere „Hallo von einer asynchronen Funktion“ } asynchrone Funktion ausführen() { const message = warte auf Begrüßung(); console.log(Nachricht) } Hier sind einige Faustregeln, die wir uns merken müssen. 👉Wait kann nur in asynchronen Funktionen verwendet werden Wenn wir await innerhalb einer Funktion verwenden, müssen wir eine Funktion deklarieren, aber nicht umgekehrt. Lassen Sie es mich so sagen. Wenn Sie „Await“-Anweisungen innerhalb einer Methode verwenden, muss es sich bei dieser Methode um eine asynchrone Methode handeln, sonst gibt der Compiler ein Problem aus. asynchrone Funktion greet() { returniere „Hallo von einer asynchronen Funktion“; } function execute() { //diese Funktion muss asynchron sein const message = warte auf Begrüßung(); console.log(Nachricht) } /* SyntaxError: „await“ ist nur in der asynchronen Funktion gültig. */ Aber das Deklarieren einer Funktion als asynchron bedeutet nicht unbedingt, dass wir darin immer darauf warten. Hier ist greet() eine asynchrone Methode, sie enthält aber keine Await-Anweisung. Warten ist nur beim Aufrufen einer Funktion sinnvoll, die ein Versprechen zurückgibt oder eine asynchrone Funktion ist. //keine asynchrone Funktion Funktion Begrüßung() { returniere „Hallo von einer asynchronen Funktion“; } asynchrone Funktion ausführen() { const message = warte auf Begrüßung(); console.log(message); //Hallo von einer asynchronen Funktion } Obwohl der Code genauso funktioniert wie der vorherige, macht es keinen Sinn, dass await auf eine synchrone Funktion zugreift. Ich würde gerne wissen, was Sie darüber denken? Ein wichtiger Aspekt bei der Verwendung von „await“ besteht darin, dass die Ausführung der nächsten Codezeile blockiert wird, bis der „await“-Block ausgeführt wird. const asyncGreet = () => neues Versprechen(auflösen => setTimeout(auflösen, 2000)); (asynchrone Funktion ausführen() { console.log("vor der Ausführung"); await asyncGreet(); //blockiert die Ausführung hier // 👇 wird ausgeführt, sobald der Wartevorgang abgeschlossen ist console.log("Ich werde nach 2000ms ausgeführt"); })(); Jetzt fragen Sie sich bestimmt: Wenn „wait“ den Code synchronisiert, warum verwenden wir es dann? NodeJs oder Browser-Javascript sind Single-Thread-Umgebungen, die jeweils eine Aufgabe ausführen und aufgrund ihres asynchronen Verhaltens, das wir verlieren, weit verbreitet sind. Was ist dann der Sinn? Ja, Sie haben Recht, aber beobachten Sie, dass wir in den meisten Fällen Aufgaben in Beziehung zu anderen ausführen müssen. asynchrone Funktion subscribeToNewsLetter() { const Benutzer = warte auf Benutzer finden(ID); //👇Methoden benötigen zur Ausführung die E-Mail-Adresse des Benutzers warte auf Abonnement (Benutzer-E-Mail) warte auf sendNotification(user.email) } Stimmt, aber was ist mit nicht damit zusammenhängendem Code? Nun, es gibt eine alternative Methode, nämlich (Promise.all). const asyncGreet = (Name) => neues Promise((Auflösung) => setTimeout(Auflösung(`Hallo ${name}`), 2000)); Konstantennamen = ['John', 'Jane', 'David']; (asynchrone Funktion() { const GreetingPromises = Namen.map(name => asyncGreet(name)); console.log (warte auf Promise.all (GreetingPromises)); })(); Ich weiß, dass der obige Code ein konstruiertes Beispiel ist. Wichtig ist hier, dass wir die Leistung von Promise.all nutzen, um alle Versprechen auszuführen. Fehlerbehandlung mit Async/Await.Die Fehlerbehandlung mit async/await ist ziemlich einfach und wir können hierzu unseren alten Freund, den Try/Catch-Block, verwenden. asynchrone Funktion subscribeToNewsLetter() { versuchen { const Benutzer = warte auf Benutzer finden(ID); warte auf Abonnement (Benutzer-E-Mail) warte auf sendNotification(user.email) } Fang(Fehler) { //Fehler behandeln } } Es gibt eine andere Version, bei der wir den Catch-Handler direkt an den Await-Block anhängen können. Ich persönlich verwende es nicht, aber Sie können es ausprobieren, wenn Sie möchten. warte auf asyncGreet().catch(err => console.log(err); 2x besser lesbar und einfacher zu debuggen Der folgende Code verwendet ein Promise, um einen Benutzer anhand der ID zu finden, die Profilinformationen zuzuweisen und dann die Abonnements des Benutzers zu finden. Funktion getUser(id, Profil) { returniere neues Promise((lösen, ablehnen) => { Benutzer .find(ich würde) .then((Benutzer) => { if(_.isEmpty(Benutzer)) return {}; Benutzer.Profil = Profil; Benutzer zurückgeben; }) .then((Benutzer) => Abonnement.find(Benutzer-ID)) .dann(Abonnement => { wenn(_.isEmpty(Abonnement)) { Benutzer.Abonnement = null; } anders { Benutzer.Abonnement = Abonnement; } returniere Auflösung (Benutzer) }) .catch(err => ablehnen(err)) }) } Der obige Code funktioniert einwandfrei, aber wir können ihn mit async/await definitiv lesbarer, prägnanter und einfacher zu debuggen machen. Lass uns gehen. asynchrone Funktion getUser(id, profile) { versuchen { const Benutzer = warte auf Benutzer.find(id); if(_.isEmpty(Benutzer)) return {}; Benutzer.Profil = Profil; const-Abonnement = warte auf Abonnement.find(Benutzer-ID); user.subscription = Abonnement Benutzer zurückgeben; } Fang(Fehler) { console.log(fehler); } } Callbacks und Async/Await sind FeindeWie wir bereits in vorherigen Beispielen gesehen haben, funktionieren Promises sehr gut mit async/await. Jede Funktion, die ein Versprechen zurückgibt, kann mit der Await-Anweisung verwendet werden. Bei Callbacks ist jedoch das Gegenteil der Fall. Callbacks können nicht direkt mit async/await verwendet werden. Sie müssen in Promises umgewandelt werden. Betrachten wir die folgende Funktion, die asynchron prüft, ob ein Wert gerade ist (gibt einen Fehler aus). Funktion asyncEven(id, cb){ setzeTimeout(() => { const gerade = id%2 === 0; wenn (gerade) return cb(null, "gerade"); sonst returniere cb("nicht einmal"); }, 2000); } Wir wissen, dass „await“ in Rückrufen nicht zulässig ist, aber versuchen wir es trotzdem. (asynchrone Funktion() { //🐶👹 Falscher Weg const even = warte auf asyncEven(2); console.log("isEven ", gerade); //undefiniert })(); Sie denken bestimmt, wir hätten keinen Rückruf angehängt und deshalb wird „undefined“ ausgegeben. Lassen Sie uns einen Rückruf anhängen, was seltsam ist, aber lassen Sie uns geduldig sein. (asynchrone Funktion() { //das ist auch falsch 🐶👹 const even = await asyncEven(2, (err, data) => { console.log("innerhalb von await auf Rückruf", err, data)}); console.log("istGerade ", gerade); })(); /* Ausgabe: sogar undefiniert im Inneren warten auf Rückruf sogar null */ Es scheint, dass der Rückruf aufgerufen wird und wir auch den Wert von der Funktion asyncEven erhalten. Das stimmt, aber es ist trotzdem der falsche Ansatz. „await“ hat keine Auswirkungen auf Rückrufe. Dies ist vergleichbar mit dem Warten auf eine synchrone Funktion. Warum wird also „undefiniert“ zurückgegeben? Das ist eine gute Frage. Dies ist die Standardnatur der asynchronen Programmierung. Die Funktion setTimeout ist ein Rückruf, der den Rückrufwert nach 2000 Millisekunden zurückgibt, während das Steuerelement mit der Ausführung der nächsten Codezeile beginnt und die Funktion erreicht. Deshalb erhalten wir am Ende „undefiniert“. Was ist also die Lösung? Es ist ganz einfach, die Funktion „asyncEven“ in ein Versprechen umzuwandeln und „await“ wie ein Champion zu verwenden. Funktion asyncEven(id,) { returniere neues Promise((lösen, ablehnen) => { setzeTimeout(() => { const gerade = id%2 === 0; wenn (gerade) return resolve("gerade"); sonst returniere „ablehnen(‚nicht einmal‘); }, 2000); }) } (asynchrone Funktion() { // wartet auf die Ausführung const even = warte auf asyncEven(2); console.log("ist gerade ", gerade); })(); ForEach ist nicht für Async/Await geeignetEs kann zu Nebenwirkungen kommen, wenn wir eine ForEach-Schleife mit async/await verwenden. Betrachten Sie das folgende Beispiel. Die Anweisung console.log wartet hier nicht auf „await“ grüße(Name). asynchrone Funktion greet(Name) { return Promise.resolve(`Hallo ${name}, wie geht es dir?`); } (Funktion() { console.log("vor dem Drucken von Namen"); Konstantennamen = ['John', 'Jane', 'Joe']; Namen.fürJeden(async (Name) => { //wartet hier nicht console.log(warte auf Begrüßung(Name)); }); console.log("nach dem Drucken von Namen"); })(); /* vor dem Drucken von Namen nach dem Drucken von Namen Hallo John, wie geht es dir? Hallo Jane, wie geht es dir? Hallo Joe, wie geht es dir? */ Mehr als nur syntaktischer ZuckerBisher wissen wir nur, dass async/await unseren Code lesbarer und debugfreundlicher macht, und manche Leute sagen, es sei eine Art Syntaxvereinfachung für JavaScript-Promises. Eigentlich ist es mehr als nur syntaktischer Zucker. // versprechen async1() .then(x => asyncTwo(x)) .then(y => asyncThree(y)) //andere Anweisung console.log("hallo") //asynchron warten x = warte auf async1(); y = warte auf asyncTwo(x); warte auf asyncThree(y); „await“ unterbricht die Ausführung der aktuellen Funktion, während „promise“ die Ausführung der aktuellen Funktion fortsetzt und den Wert zu „then()“ hinzufügt. Zwischen den beiden Durchführungsarten bestehen erhebliche Unterschiede. Lassen Sie es mich erklären. Betrachten Sie die Promise-Version. Wenn asyncTwo() oder asyncThree() beim Ausführen der Aufgabe einen asynchronen Fehler auslösen, wird dann async1() in den Stacktrace aufgenommen? Hier unterbricht das Promise die Ausführung der aktuellen Funktion nicht. Wenn asyncTwo es auflöst oder ablehnt, liegt der Kontext nicht innerhalb der Promise-Anweisung. Daher darf „asyncOne“ im Idealfall nicht im Stacktrace enthalten sein. Aber dank der V8-Engine kann hier etwas Magisches geschehen und asyncOne() wird in den Kontext aufgenommen, indem im Voraus darauf verwiesen wird. Aber es ist nicht kostenlos. Das Erfassen eines Stacktraces nimmt Zeit in Anspruch (d. h. es verringert die Leistung). Das Speichern dieser Stapeltraces erfordert Speicher. Hier übertrifft async/await Promises in puncto Leistung, da die Ausführung der aktuellen Funktion angehalten wird, bis die erwartete Funktion abgeschlossen ist, sodass wir bereits über einen Verweis auf diese Funktion verfügen. ZusammenfassenDies ist das Ende dieses Artikels über asynchrones Warten in Javascript. Weitere relevante Inhalte zum asynchronen Warten in Javascript finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: Einfache Zusammenfassung der Methoden zur Leistungsoptimierung von Tomcat
>>: Erläuterung des MySQL-Multitabellen-Join-Abfragebeispiels
Object.defineProperty verstehen Grammatik: Object...
Inhaltsverzeichnis Vorwort Installieren des Grafi...
Um Node-red mit der Datenbank (mysql) zu verbinde...
Ich habe vor Kurzem angefangen, das NestJs-Framew...
Suchen Sie die Container-ID von Tomcat und rufen ...
Vorwort Es besteht ein Missverständnis bezüglich ...
Einführung Beginnen wir wie immer mit einer Szene...
Inhaltsverzeichnis Komplexe Abfrage und schrittwe...
Inhaltsverzeichnis 1. Einleitung 2. Komponentenen...
Ich habe vorher ein Testprogramm geschrieben, in d...
So ändern Sie das Passwort in MySQL 5.7.18: 1. Fa...
Inhaltsverzeichnis Hintergrund: brauchen: Wirkung...
Freunde, die Speicherplatz gekauft und Websites er...
MySQL ist heute die Datenbank, die von den meiste...
MySQL Workbench – Modellierungs- und Designtool 1...