Was ist der Unterschied zwischen JavaScript-Versprechen und asynchronem Warten?

95

Ich habe bereits ECMAScript 6- und ECMAScript 7-Funktionen (dank Babel) in meinen Anwendungen verwendet - sowohl für Mobilgeräte als auch für das Internet.

Der erste Schritt war offensichtlich die ECMAScript 6-Ebene. Ich habe viele asynchrone Muster gelernt, die Versprechen (die wirklich vielversprechend sind), Generatoren (nicht sicher, warum das * -Symbol) usw. Von diesen passten Versprechen ziemlich gut zu meinem Zweck. Und ich habe sie in meinen Anwendungen ziemlich oft verwendet.

Hier ist ein Beispiel / Pseudocode, wie ich ein grundlegendes Versprechen umgesetzt habe.

var myPromise = new Promise(
    function (resolve,reject) {
      var x = MyDataStore(myObj);
      resolve(x);
    });

myPromise.then(
  function (x) {
    init(x);
});

Als die Zeit verging, stieß ich auf ECMAScript 7 - Features und einer von ihnen ASYNCund AWAITSchlüsselwörter / Funktionen. Diese zusammen bewirken große Wunder. Ich habe begonnen, einige meiner Versprechen durch zu ersetzen async & await. Sie scheinen dem Programmierstil einen großen Mehrwert zu verleihen.

Auch hier ist ein Pseudocode, wie meine asynchrone Wartefunktion aussieht:

async function myAsyncFunction (myObj) {
    var x = new MyDataStore(myObj);
    return await x.init();
}
var returnVal = await myAsyncFunction(obj);

Abgesehen von den Syntaxfehlern (falls vorhanden) tun beide genau das, was ich fühle. Ich habe es fast geschafft, die meisten meiner Versprechen durch asynchrone zu ersetzen.

Warum ist Async, Warten erforderlich, wenn Versprechen einen ähnlichen Job machen?

Löst Async, Warten ein größeres Problem? Oder war es nur eine andere Lösung, um die Hölle zurückzurufen?

Wie ich bereits sagte, kann ich Versprechen verwenden und asynchron warten, um das gleiche Problem zu lösen. Gibt es etwas Spezielles, das asynchron gelöst werden kann?

Zusätzliche Bemerkungen:

Ich habe Async, Warten und Versprechen in meinen React-Projekten und Node.js-Modulen ausgiebig verwendet. Reagieren war besonders ein Frühaufsteher und hat viele Funktionen von ECMAScript 6 und ECMAScript 7 übernommen.

Bozzmob
quelle
3
Ihr erster Codeblock scheint ein Versprechen für einen synchronen Betrieb zu verwenden. Warum würdest du das tun? Synchron ist von Natur aus einfacher zu schreiben, daher sollte es wenig Grund geben, eine synchrone Operation in ein Versprechen zu packen und sie jetzt asynchron zu erzwingen.
jfriend00
@ jfriend00 Ja du hast recht. Code bearbeitet. Vielen Dank.
Bozzmob
2
Sie versuchen immer noch, asynchrone Tools mit synchronen Funktionen zu verwenden - jetzt in beiden Codeblöcken. Warum?
jfriend00
@ jfriend00 Ok. Hier habe ich meinen Code gist.github.com/bozzmob/26d38b83dc37d1be37f5 . Können Sie mir bitte sagen, was ich falsch mache?
Bozzmob
10
Es hört sich so an, als müssten Sie nur ein paar Mal lesen, um zu verstehen, worauf Async und Warten warten. Hier einige Artikel: Der lange Weg zu Async / Await in JavaScript und Vereinfachung der asynchronen Codierung mit ES7 Async-Funktionen und Zähmung des asynchronen Tieres mit ES7 .
jfriend00

Antworten:

74

Warum ist Async, Warten erforderlich, wenn Promises ähnliche Aufgaben erledigt? Löst Async, Warten ein größeres Problem?

async/awaitgibt Ihnen einfach ein synchrones Gefühl für asynchronen Code. Es ist eine sehr elegante Form von syntaktischem Zucker.

Bei einfachen Abfragen und Datenmanipulationen kann Promises einfach sein. Wenn Sie jedoch auf Szenarien stoßen, in denen komplexe Datenmanipulationen stattfinden und was nicht, ist es einfacher zu verstehen, was vor sich geht, wenn der Code einfach so aussieht, als wäre er synchron ( anders ausgedrückt: Die Syntax an und für sich ist eine Form der "zufälligen Komplexität", async/awaitdie sich umgehen kann.

Wenn Sie interessiert sind, können Sie eine Bibliothek wie co(neben Generatoren) verwenden, um das gleiche Gefühl zu vermitteln. Solche Dinge wurden entwickelt, um das Problem zu lösen, das async/awaitletztendlich (nativ) gelöst wird.

Josh Beam
quelle
Können Sie bitte näher erläutern, was "zufällige Komplexität" bedeutet? Auch wenn es um Leistung geht, gibt es keinen Unterschied zwischen den beiden?
Bozzmob
@bozzmob, shaffner.us/cs/papers/tarpit.pdf <- er erklärt dort "zufällige Komplexität". Was Ihre Leistungsfrage betrifft, bezweifle ich dies, insbesondere, wenn der V8-Motor das ist, was er ist. Ich bin mir sicher, dass es da draußen einige Perf-Tests gibt, aber darüber würde ich mir keine Sorgen machen. Verschwenden Sie Ihre Zeit nicht mit Mikrooptimierung, wenn dies nicht erforderlich ist.
Josh Beam
1
Vielen Dank! Dies sind einige großartige Informationen, die ich von Ihnen erhalten habe. Und ja, ich werde mich nicht mit Mikrooptimierungen befassen.
Bozzmob
Ich fand diese Erklärung hilfreich nikgrozev.com/2015/07/14/…
mwojtera
33

Async / Await bietet in komplexeren Szenarien eine viel schönere Syntax. Insbesondere alles, was sich mit Schleifen oder bestimmten anderen Konstrukten wie try/ befasst catch.

Beispielsweise:

while (!value) {
  const intermediate = await operation1();
  value = await operation2(intermediate);
}

Dieses Beispiel wäre nur mit Promises wesentlich komplizierter.

Stephen Cleary
quelle
Dies ist ein großartiges Beispiel, um dasselbe zu verstehen. Wenn es also um Leistung geht, gibt es keinen Unterschied zwischen den beiden? Und welches ist besser im Code zu verwenden? Async Await scheint besser zu sein, nachdem Sie mindestens Ihr Beispiel gesehen haben.
Bozzmob
1
@bozzmob: Es gibt keinen Unterschied in der Leistung. Wenn Sie mit async / await vertraut sind, würde ich es empfehlen. Ich benutze es selbst noch nicht, weil es nicht Teil des offiziellen Standards ist.
Stephen Cleary
Ja, ich bin damit einverstanden, dass es nicht Teil des Standards ist, aber im Falle von ReactJS (React Native Specific) bin ich gezwungen, es an einigen Stellen des Codes zu verwenden. Die Hälfte davon sind Versprechen und die andere Hälfte warten auf Asynchronität. Also habe ich dir diese Fragen gestellt. Danke für die bedürftigen Informationen.
Bozzmob
1
Ich denke, viele Leute sind verwirrt und / oder irregeführt, wenn niemand den try / catch-Block in ihren Codebeispielen verwendet.
Augie Gardner
Du meinst so? const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux
13

Warum ist Async, Warten erforderlich, wenn Promises ähnliche Aufgaben erledigt? Löst Async, Warten ein größeres Problem? oder war es nur eine andere Lösung, um die Hölle zurückzurufen? Wie ich bereits sagte, kann ich Promises und Async, Await verwenden, um das gleiche Problem zu lösen. Gibt es etwas Spezielles, das Async Await gelöst hat?

Das Erste, was Sie verstehen müssen, ist, dass async/ awaitsyntax nur syntaktischer Zucker ist, der Versprechen erhöhen soll. Tatsächlich ist der Rückgabewert einer asyncFunktion ein Versprechen. asyncDie awaitSyntax / gibt uns die Möglichkeit, asynchron synchron zu schreiben. Hier ist ein Beispiel:

Versprechen Verkettung:

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}

Async Funktion:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

Im obigen Beispiel wird darauf awaitgewartet, dass das Versprechen ( fetch(url)) entweder aufgelöst oder abgelehnt wird. Wenn das Versprechen aufgelöst wird, wird der Wert in der responseVariablen gespeichert , und wenn das Versprechen abgelehnt wird, wird ein Fehler ausgegeben und somit der catchBlock eingegeben .

Wir können bereits sehen, dass die Verwendung von async/ awaitmöglicherweise besser lesbar ist als die Verkettung von Versprechen. Dies gilt insbesondere dann, wenn die Anzahl der Versprechen, die wir verwenden, zunimmt. Beide Versprechen Verkettungs und async/ awaitlösen das Problem der Callback - Hölle und welche Methode Sie wählen , ist Frage des persönlichen Geschmacks.

Willem van der Veen
quelle
7

Vollständiger Vergleich mit Vor- und Nachteilen.

Einfaches JavaScript

  • Vorteile
  • Benötigt keine zusätzlichen Bibliotheken oder Technologien
  • Bietet die beste Leistung
  • Bietet die beste Kompatibilität mit Bibliotheken von Drittanbietern
  • Ermöglicht die Erstellung von Ad-hoc- und erweiterten Algorithmen
  • Nachteile
  • Möglicherweise sind zusätzlicher Code und relativ komplexe Algorithmen erforderlich

Async (Bibliothek)

  • Vorteile
  • Vereinfacht die gängigsten Kontrollflussmuster
  • Ist immer noch eine Callback-basierte Lösung
  • Gute Leistung
  • Nachteile
  • Führt eine externe Abhängigkeit ein
  • Könnte für fortgeschrittene Strömungen immer noch nicht ausreichen

Versprechen

  • Vorteile
  • Vereinfacht die gängigsten Kontrollflussmuster erheblich
  • Robuste Fehlerbehandlung
  • Teil der ES2015-Spezifikation
  • Garantiert den verzögerten Aufruf von onFulfilled und onRejected
  • Nachteile
  • Erfordert vielversprechende Callback-basierte APIs
  • Führt einen kleinen Performance-Hit ein

Generatoren

  • Vorteile
  • Lässt die nicht blockierende API wie eine blockierende aussehen
  • Vereinfacht die Fehlerbehandlung
  • Teil der ES2015-Spezifikation
  • Nachteile
  • Benötigt eine ergänzende Kontrollflussbibliothek
  • Erfordert weiterhin Rückrufe oder Versprechen, um nicht sequentielle Flows zu implementieren
  • Erfordert thunkify oder promisify nicht generatorbasierte APIs

Async warten

  • Vorteile
  • Lässt die nicht blockierende API wie blockierend aussehen
  • Saubere und intuitive Syntax
  • Nachteile
  • Benötigt Babel oder andere Transpiler und eine Konfiguration, die heute verwendet werden soll
Bozhinovski
quelle
Woher wurde das kopiert? Zumindest ein Teil davon befindet sich auf Seite 136-137 im Buch Node.js Design Patterns (zweite Ausgabe) (ISBN-10: 1785885588)
Peter Mortensen,
6

Async / await kann dazu beitragen, Ihren Code sauberer und lesbarer zu machen, wenn Sie einen komplizierten Kontrollfluss benötigen. Es erzeugt auch debug-freundlicheren Code. Und macht es möglich, sowohl synchrone als auch asynchrone Fehler mit just zu behandeln try/catch.

Ich habe kürzlich diesen Beitrag geschrieben, der die Vorteile von async / await gegenüber Versprechungen in einigen gängigen Anwendungsfällen anhand von Codebeispielen zeigt: 6 Gründe, warum JavaScript Async / Await Versprechen wegbläst (Tutorial)

gafi
quelle