Quelle est la différence entre les promesses JavaScript et l'attente asynchrone?

97

J'utilise déjà les fonctionnalités ECMAScript 6 et ECMAScript 7 (grâce à Babel) dans mes applications - mobiles et Web.

La première étape était évidemment les niveaux ECMAScript 6. J'ai appris de nombreux modèles asynchrones, les promesses (qui sont vraiment prometteuses), les générateurs (je ne sais pas pourquoi le symbole *), etc. Et je les utilise beaucoup dans mes applications.

Voici un exemple / pseudocode de la façon dont j'ai mis en œuvre une promesse de base -

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

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

Au fil du temps, je suis tombé sur ECMAScript 7 caractéristiques, et l' un d'entre eux étant ASYNCet AWAITmots - clés / fonctions. Tout cela fait de grandes merveilles. J'ai commencé à remplacer certaines de mes promesses par async & await. Ils semblent ajouter une grande valeur au style de programmation.

Encore une fois, voici un pseudo-code de l'apparence de ma fonction async, wait -

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

En gardant de côté les erreurs de syntaxe (le cas échéant), les deux font exactement la même chose, c'est ce que je ressens. J'ai presque pu remplacer la plupart de mes promesses par async, attend.

Pourquoi async, wait est-il nécessaire lorsque les promesses font un travail similaire?

Async, wait résout-il un problème plus important? Ou était-ce juste une solution différente pour l'enfer des rappels?

Comme je l'ai dit plus tôt, je suis capable d'utiliser les promesses et l'asynchrone, en attendant de résoudre le même problème. Y a-t-il quelque chose de spécifique que l'async attend d'être résolu?

Notes complémentaires:

J'ai beaucoup utilisé async, attend et promet dans mes projets React et les modules Node.js. React a surtout été un précurseur et a adopté de nombreuses fonctionnalités ECMAScript 6 et ECMAScript 7.

bozzmob
la source
3
Votre premier bloc de code semble utiliser une promesse pour une opération synchrone. Pourquoi ferais-tu ça? Synchrone est, par nature, plus facile à écrire du code, il ne devrait donc y avoir aucune raison d'envelopper une opération synchrone dans une promesse et de la forcer à être maintenant asynchrone.
jfriend00
@ jfriend00 Oui, vous avez raison. Modifié le code. Merci.
bozzmob
2
Vous essayez toujours d'utiliser des outils asynchrones avec des fonctions synchrones - maintenant dans les deux blocs de code. Pourquoi?
jfriend00
@ jfriend00 Ok. Ici, j'ai mon code gist.github.com/bozzmob/26d38b83dc37d1be37f5 . Pouvez-vous me dire ce que je fais de mal?
bozzmob
10
Il semble que vous ayez juste besoin de faire beaucoup de lecture pour comprendre à quoi servent async et wait. Voici quelques articles: Le long chemin vers Async / Await en JavaScript et simplifier le codage asynchrone avec les fonctions asynchrones d'ES7 et apprivoiser la bête asynchrone avec ES7 .
jfriend00

Réponses:

75

Pourquoi async, wait est-il nécessaire lorsque Promises fait un travail similaire? Async, wait résout-il un problème plus important?

async/awaitvous donne simplement une sensation synchrone avec le code asynchrone. C'est une forme très élégante de sucre syntaxique.

Pour les requêtes simples et la manipulation de données, les promesses peuvent être simples, mais si vous rencontrez des scénarios où il y a manipulation de données complexes et ce qui n'est pas impliqué, il est plus facile de comprendre ce qui se passe si le code semble simplement synchrone (pour le dire autrement, la syntaxe en elle-même est une forme de «complexité incidente» qui async/awaitpeut se déplacer).

Si vous êtes intéressé à savoir, vous pouvez utiliser une bibliothèque comme co(à côté des générateurs) pour donner le même genre de sensation. Des choses comme celle-ci ont été développées pour résoudre le problème qui async/awaitfinalement résout (nativement).

Josh Beam
la source
Pouvez-vous préciser ce que signifie «complexité incidente»? Aussi, quand il s'agit de performances, il n'y a pas de différence entre les deux?
bozzmob
@bozzmob, shaffner.us/cs/papers/tarpit.pdf <- il y explique la "complexité incidente". En ce qui concerne votre question de performance, j'en doute, d'autant plus que le moteur V8 est ce qu'il est. Je suis sûr qu'il existe des tests de performance, mais je ne m'en soucierais pas trop. Ne perdez pas votre temps en micro-optimisation quand ce n'est pas nécessaire.
Josh Beam
1
Merci beaucoup! Voici quelques informations intéressantes que j'ai obtenues de vous. Et oui, ne se penchera pas sur les micro-optimisations.
bozzmob
J'ai trouvé cette explication utile nikgrozev.com/2015/07/14/…
mwojtera
33

Async / Await fournit une syntaxe beaucoup plus agréable dans des scénarios plus complexes. En particulier, tout ce qui concerne les boucles ou certaines autres constructions comme try/ catch.

Par exemple:

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

Cet exemple serait considérablement plus compliqué en utilisant simplement des promesses.

Stephen Cleary
la source
Ceci est un excellent exemple pour comprendre la même chose. Alors, quand il s'agit de performances, il n'y a pas de différence entre les deux? Et quel est le meilleur à utiliser dans le code? Async Await semble mieux après avoir vu votre exemple au moins.
bozzmob
1
@bozzmob: Il n'y a pas de différence de performances. Si vous êtes à l'aise avec async / await, je le recommanderais. Je ne l'utilise pas encore moi-même car il ne fait pas partie de la norme officielle.
Stephen Cleary
Oui, je suis d'accord que ce n'est pas une partie de la norme, mais, dans le cas de ReactJS (réagir natif spécifiquement), je suis un peu obligé de l'utiliser dans certaines parties du code. Ainsi, la moitié d'entre elles sont des promesses et l'autre moitié sont des attentes asynchrones. Alors, je vous ai posé ces questions. Merci pour les informations nécessaires.
bozzmob
1
Je pense que beaucoup de gens sont confus et / ou induits en erreur lorsque personne n'utilise le bloc try / catch dans leurs échantillons de code.
Augie Gardner
Tu veux dire comme ça? const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux
13

Pourquoi async, wait est-il nécessaire lorsque Promises fait un travail similaire? Async, wait résout-il un problème plus important? ou était-ce juste une solution différente à l'enfer des rappels? Comme je l'ai dit plus tôt, je suis capable d'utiliser Promises et Async, Await pour résoudre le même problème. Async Await a-t-il résolu quelque chose de spécifique?

La première chose que vous devez comprendre que async/ awaitsyntax est juste du sucre syntaxique qui est destiné à augmenter les promesses. En fait, la valeur de retour d'une asyncfonction est une promesse. async/ awaitsyntax nous donne la possibilité d'écrire de manière asynchrone de manière synchrone. Voici un exemple:

Enchaînement des promesses:

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

Async fonction:

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

Dans l'exemple ci-dessus, awaitattend que la promesse ( fetch(url)) soit résolue ou rejetée. Si la promesse est résolue, la valeur est stockée dans la responsevariable, et si la promesse est rejetée, elle lèverait une erreur et entrerait ainsi dans le catchbloc.

Nous pouvons déjà voir que l'utilisation de async/ awaitpourrait être plus lisible que le chaînage de promesses. Cela est particulièrement vrai lorsque le nombre de promesses que nous utilisons augmente. Les deux Promise enchaînent et async/ awaitrésolvent le problème de l'enfer du rappel et la méthode que vous choisissez est une question de préférence personnelle.

Willem van der Veen
la source
7

Comparaison complète avec les avantages et les inconvénients.

JavaScript simple

  • Avantages
  • Ne nécessite aucune bibliothèque ou technologie supplémentaire
  • O re les meilleures performances
  • Fournit le meilleur niveau de compatibilité avec les bibliothèques tierces
  • Permet la création d'algorithmes ad hoc et plus avancés
  • Les inconvénients
  • Peut nécessiter du code supplémentaire et des algorithmes relativement complexes

Async (bibliothèque)

  • Avantages
  • Simplifie les schémas de contrôle les plus courants
  • Est toujours une solution basée sur le rappel
  • Bonne performance
  • Les inconvénients
  • Introduit une dépendance externe
  • Peut-être encore insuffisant pour les fl ux avancés

Promesses

  • Avantages
  • Simplifie considérablement les schémas de fl ux de contrôle les plus courants
  • Gestion des erreurs robuste
  • Fait partie de la spéci fi cation ES2015
  • Garantit l'invocation différée de onFulfilled et onRejected
  • Les inconvénients
  • Nécessite des API basées sur le rappel promisify
  • Introduit un petit succès de performance

Générateurs

  • Avantages
  • Rend l'API non bloquante comme une API bloquante
  • Simplifie la gestion des erreurs
  • Fait partie de la spéci fi cation ES2015
  • Les inconvénients
  • Nécessite une bibliothèque de flux de contrôle complémentaire
  • Nécessite toujours des rappels ou des promesses pour implémenter des flux non séquentiels
  • Nécessite des API thunkify ou promisify non basées sur les générateurs

Attendre asynchrone

  • Avantages
  • Donne l'apparence d'une API non bloquante à un blocage
  • Syntaxe claire et intuitive
  • Les inconvénients
  • Nécessite Babel ou d'autres transpileurs et une configuration pour être utilisé aujourd'hui
Johnny
la source
D'où cela a-t-il été copié? Au moins une partie est à la page 136-137 dans le livre Node.js Design Patterns (deuxième édition) (ISBN-10: 1785885588)
Peter Mortensen
6

Async / await peut aider à rendre votre code plus propre et plus lisible dans les cas où vous avez besoin d'un flux de contrôle compliqué. Il produit également un code plus convivial pour le débogage. Et permet de gérer les erreurs synchrones et asynchrones avec juste try/catch.

J'ai récemment écrit cet article montrant les avantages d'async / await par rapport aux promesses dans certains cas d'utilisation courants avec des exemples de code: 6 raisons pour lesquelles JavaScript Async / Await Blows Promises Away (Tutoriel)

gafi
la source