web-dev-qa-db-fra.com

Quelles sont les différences entre JavaScript, Deferred, Promise et Future?

Quelles sont les différences entre différés, promesses et futures?
Existe-t-il une théorie généralement approuvée derrière ces trois concepts?

296
Tower

À la lumière d'une aversion apparente pour la façon dont j'ai tenté de répondre à la question du PO. La réponse littérale est qu'une promesse est quelque chose qui est partagé avec d'autres objets, alors qu'une différée doit rester privée. En premier lieu, une promesse différée (qui étend généralement la promesse) peut se résoudre, alors qu'une promesse pourrait ne pas être en mesure de le faire.

Si les minuties vous intéressent, examinez Promises/A + .


À ma connaissance, l'objectif principal est d'améliorer la clarté et de relâcher le couplage via une interface normalisée. Voir lecture suggérée de @ jfriend00:

Plutôt que de transmettre directement des rappels aux fonctions, ce qui peut conduire à des interfaces étroitement couplées, l'utilisation de promesses permet de séparer les problèmes de code synchrone ou asynchrone.

Personnellement, j’ai trouvé le report différé particulièrement utile lorsqu’il s’agit par exemple de des modèles remplis par des demandes asynchrones, chargeant des scripts comportant des réseaux de dépendances et fournissant des informations en retour à l'utilisateur afin de former les données de manière non bloquante.

En effet, comparez la forme de rappel pur de faire quelque chose après avoir chargé CodeMirror en mode JS de manière asynchrone (excuses, je n'ai pas utilisé jQuery dans un tant que ):

/* assume getScript has signature like: function (path, callback, context) 
   and listens to onload && onreadystatechange */
$(function () {
   getScript('path/to/CodeMirror', getJSMode);

   // onreadystate is not reliable for callback args.
   function getJSMode() {
       getScript('path/to/CodeMirror/mode/javascript/javascript.js', 
           ourAwesomeScript);
   };

   function ourAwesomeScript() {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   };
});

Pour les promesses version formulée (encore une fois, excusez-moi, je ne suis pas à jour sur jQuery):

/* Assume getScript returns a promise object */
$(function () {
   $.when(
       getScript('path/to/CodeMirror'),
       getScript('path/to/CodeMirror/mode/javascript/javascript.js')
   ).then(function () {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   });
});

Toutes mes excuses pour le semi-pseudo-code, mais j'espère que cela clarifie l'idée de base. Fondamentalement, en retournant une promesse standardisée, vous pouvez la faire passer, permettant ainsi un regroupement plus clair.

96
fncomp

Ces réponses, y compris la réponse sélectionnée, sont bonnes pour introduire des promesses de manière conceptuelle, mais manquent de détails sur les différences entre la terminologie apparaissant lors de l'utilisation de bibliothèques les implémentant (et sont différences importantes).

Comme il s'agit toujours de ne spécification en évolution , la réponse provient actuellement d'une tentative d'enquête sur les deux références (comme wikipedia ) et les implémentations (comme jQuery ):

  • Différé : jamais décrit dans des références populaires, 124 mais couramment utilisé par les implémentations comme arbitre de la résolution des promesses (implémentation de resolve et reject). 567

    Parfois, les reports sont aussi des promesses (implémentation de then), 56 D'autres fois, il est considéré comme plus pur de ne pouvoir résoudre que le différé, et d'obliger l'utilisateur à accéder à la promesse d'utiliser then7

  • Promise : le mot le plus complet pour la stratégie en discussion.

    Un objet proxy stockant le résultat d'une fonction cible dont nous voudrions résumer la synchronicité, plus l'exposition d'une fonction then acceptant une autre fonction cible et renvoyant une nouvelle promesse. 2

    Exemple de CommonJS :

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44
    

    Toujours décrit dans des références populaires, bien que jamais précisé quant à la responsabilité de laquelle revient la résolution 124

    Toujours présent dans les implémentations populaires et jamais doté de capacités de résolution. 567

  • Future : terme apparemment obsolète trouvé dans certaines références populaires 1 et au moins une implémentation populaire, 8 mais apparemment en train d'être éliminé de la discussion de préférence au terme "promesse"  et pas toujours mentionné dans les introductions populaires au sujet. 9

    Cependant, au moins une bibliothèque utilise le terme de manière générique pour résumer la synchronicité et le traitement des erreurs, sans fournir la fonctionnalité then1 Il n'est pas clair si éviter le terme "promesse" était intentionnel, mais c'est probablement un bon choix, car les promesses sont construites autour de "thenables". 2

Références

  1. Wikipedia sur Promises & Futures
  2. Promises/A + spec
  3. DOM Standard on Promises
  4. DOM Standard Promises Spec WIP
  5. boîte à outils DOJO différée
  6. jQuery différé
  7. Q
  8. FutureJS
  9. section Javascript fonctionnelle sur les promesses
  10. Futures in AngularJS Integration Testing

Divers choses potentiellement déroutantes

143
Woahdae

Ce qui a vraiment fait tout cliquer pour moi a été cette présentation par Domenic Denicola.

Dans un github Gist , il a donné la description que j'aime le plus, c'est très concis:

Le but des promesses est de nous redonner une composition fonctionnelle et des erreurs dans le monde asynchrone.

En d'autres mots, les promesses sont un moyen qui nous permet d'écrire un code asynchrone presque aussi facile à écrire que s'il était synchrone .

Considérez cet exemple, avec des promesses:

getTweetsFor("domenic") // promise-returning async function
    .then(function (tweets) {
        var shortUrls = parseTweetsForUrls(tweets);
        var mostRecentShortUrl = shortUrls[0];
        return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
    })
    .then(doHttpRequest) // promise-returning async function
    .then(
        function (responseBody) {
            console.log("Most recent link text:", responseBody);
        },
        function (error) {
            console.error("Error with the twitterverse:", error);
        }
    );

Cela fonctionne comme si vous écriviez ce code synchrone:

try {
    var tweets = getTweetsFor("domenic"); // blocking
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
    console.log("Most recent link text:", responseBody);
} catch (error) {
    console.error("Error with the twitterverse: ", error);
}

(Si cela semble encore compliqué, regardez cette présentation!)

Concernant le différé, c'est un moyen de .resolve() ou .reject() promesses. Dans la spécification Promises/B , il est appelé .defer(). Dans jQuery, c'est $.Deferred().

Veuillez noter que, pour autant que je sache, l'implémentation de Promise dans jQuery est en panne (voir ce Gist), au moins à partir de jQuery 1.8.2.
Il est supposé implémenter Promises/A thenables , mais vous n'obtenez pas le traitement d'erreur correct, vous devriez, dans le sens où la fonctionnalité "async try/catch" ne fonctionnera pas . Ce qui est dommage, car avoir un "try/catch" avec du code asynchrone est tout à fait cool.

Si vous allez utiliser Promises (vous devriez les essayer avec votre propre code!), Utilisez Q de Kris Kowal . La version de jQuery est juste un agrégateur de callback pour écrire du code jQuery plus propre, mais passe à côté de l’essentiel.

En ce qui concerne Future, je n'en ai aucune idée, je ne l'ai jamais vu dans aucune API.

Edit: Discussion youtube de Domenic Denicola sur Promises à partir du commentaire de @ Farm ci-dessous.

Une citation de Michael Jackson (oui, Michael Jackson ) de la vidéo:

Je veux que vous graviez cette phrase dans votre esprit: Une promesse est une valeur asynchrone .

C'est une excellente description: une promesse est comme une variable du futur - une référence de premier ordre à quelque chose qui, à un moment donné, existera (ou se produira).

72
Camilo Martin

Une promesse représente un proxy pour une valeur non nécessairement connue lors de la création de la promesse. Il vous permet d'associer des gestionnaires à la valeur de succès ou au motif d'échec d'une action asynchrone. Cela permet aux méthodes asynchrones de retourner des valeurs comme des méthodes synchrones: au lieu de la valeur finale, la méthode asynchrone renvoie la promesse d'avoir une valeur à un moment donné dans le futur.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

La méthode deferred.promise() permet à une fonction asynchrone d'empêcher un autre code d'interférer avec la progression ou le statut de sa requête interne. La promesse expose uniquement les méthodes différées nécessaires pour associer des gestionnaires supplémentaires ou déterminer l’état (, puis, terminé, échouer, toujours, diriger, progresser, indiquer et promettre ), mais pas ceux qui changent l’état ( résoudre, rejeter, notifier, resolWith, rejetWith et notifyWith ).

Si target est fourni, deferred.promise() y attachera les méthodes, puis retournera cet objet plutôt que d'en créer un nouveau. Cela peut être utile pour associer le comportement Promise à un objet qui existe déjà.

Si vous créez un différé, conservez une référence au différé afin qu’elle puisse être résolue ou rejetée à un moment donné. Renvoie uniquement l'objet Promise via deferred.promise () afin qu'un autre code puisse enregistrer des rappels ou inspecter l'état actuel.

Nous pouvons simplement dire qu’une promesse représente une valeur qui n’est pas encore connue, où en tant que différée représente un travail qui n'est pas encore terminé.


enter image description here

29
IRSHAD
  • Un promise représente une valeur inconnue
  • Un deferred représente un travail qui n'est pas encore terminé

Une promesse est un espace réservé pour un résultat initialement inconnu, tandis qu'une différé représente le calcul qui aboutit à la valeur.

Référence

22
mattLummus