Que signifie alors la fonction () en JavaScript?


Réponses:


349

La façon traditionnelle de traiter les appels asynchrones en JavaScript a été avec les rappels. Supposons que nous devions passer trois appels au serveur, l'un après l'autre, pour configurer notre application. Avec les rappels, le code pourrait ressembler à ceci (en supposant une fonction xhrGET pour effectuer l'appel du serveur):

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

Dans cet exemple, nous récupérons d'abord la configuration du serveur. Sur cette base, nous récupérons des informations sur l'utilisateur actuel, puis obtenons enfin la liste des éléments pour l'utilisateur actuel. Chaque appel xhrGET prend une fonction de rappel qui est exécutée lorsque le serveur répond.

Maintenant, bien sûr, plus nous avons de niveaux d'imbrication, plus le code est difficile à lire, déboguer, maintenir, mettre à niveau et travailler avec. Ceci est généralement connu comme l'enfer de rappel. De plus, si nous avions besoin de gérer des erreurs, nous devons éventuellement passer une autre fonction à chaque appel xhrGET pour lui dire ce qu'il doit faire en cas d'erreur. Si nous voulions avoir un seul gestionnaire d'erreur commun, ce n'est pas possible.

L'API Promise a été conçue pour résoudre ce problème d'imbrication et le problème de gestion des erreurs.

L'API Promise propose les éléments suivants:

  1. Chaque tâche asynchrone renverra un promiseobjet.
  2. Chaque promiseobjet aura une thenfonction qui peut prendre deux arguments, un success gestionnaire et un errorgestionnaire.
  3. Le succès ou le gestionnaire d'erreurs dans la thenfonction sera appelé une seule fois , une fois la tâche asynchrone terminée.
  4. La thenfonction renverra également a promise, pour permettre de chaîner plusieurs appels.
  5. Chaque gestionnaire (succès ou erreur) peut retourner un value, qui sera passé à la fonction suivante en tant que argument, dans la chaîne de promises.
  6. Si un gestionnaire renvoie un promise(effectue une autre demande asynchrone), le gestionnaire suivant (succès ou erreur) sera appelé uniquement une fois cette demande terminée.

Ainsi, l'exemple de code précédent peut se traduire par quelque chose comme le suivant, en utilisant des promesses et le $httpservice (dans AngularJs):

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

Propager le succès et l'erreur

Le chaînage des promesses est une technique très puissante qui nous permet d'accomplir de nombreuses fonctionnalités, comme faire appel à un service par un serveur, effectuer un certain post-traitement des données, puis renvoyer les données traitées au contrôleur. Mais lorsque nous travaillons avec des promisechaînes, il y a certaines choses que nous devons garder à l'esprit.

Considérons la promisechaîne hypothétique suivante avec trois promesses, P1, P2 et P3. Chacun promisea un gestionnaire de réussite et un gestionnaire d'erreur, donc S1 et E1 pour P1, S2 et E2 pour P2, et S3 et E3 pour P3:

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

Dans le flux normal des choses, où il n'y a pas d'erreurs, l'application passerait par S1, S2 et enfin S3. Mais dans la vraie vie, les choses ne sont jamais aussi fluides. P1 peut rencontrer une erreur, ou P2 peut rencontrer une erreur, déclenchant E1 ou E2.

Considérez les cas suivants:

• Nous recevons une réponse réussie du serveur dans P1, mais les données retournées ne sont pas correctes ou il n'y a pas de données disponibles sur le serveur (pensez tableau vide). Dans un tel cas, pour la prochaine promesse P2, il devrait déclencher le gestionnaire d'erreur E2.

• Nous recevons une erreur pour la promesse P2, déclenchant E2. Mais à l'intérieur du gestionnaire, nous avons des données du cache, garantissant que l'application peut se charger normalement. Dans ce cas, nous pourrions vouloir nous assurer qu'après E2, S3 est appelé.

Ainsi, chaque fois que nous écrivons un succès ou un gestionnaire d'erreurs, nous devons faire un appel - étant donné notre fonction actuelle, cette promesse est-elle un succès ou un échec pour le gestionnaire suivant dans la chaîne de promesses?

Si nous voulons déclencher le gestionnaire de réussite pour la prochaine promesse de la chaîne, nous pouvons simplement renvoyer une valeur du gestionnaire de réussite ou d'erreur

Si, d'autre part, nous voulons déclencher le gestionnaire d'erreurs pour la prochaine promesse de la chaîne, nous pouvons le faire en utilisant un deferredobjet et en appelant sa reject()méthode

Maintenant Qu'est-ce qu'un objet différé?

Les objets différés dans jQuery représentent une unité de travail qui sera terminée plus tard, généralement de manière asynchrone. Une fois l'unité de travail terminée, l' deferredobjet peut être défini sur résolu ou échoué.

Un deferredobjet contient un promiseobjet. Via l' promiseobjet, vous pouvez spécifier ce qui doit se produire une fois l'unité de travail terminée. Pour ce faire, définissez des fonctions de rappel sur l' promiseobjet.

Objets différés dans Jquery: https://api.jquery.com/jquery.deferred/

Objets différés dans AngularJs: https://docs.angularjs.org/api/ng/service/ $ q


3
Très bien écrit. Cela m'a vraiment aidé à tenir mes promesses.
Ju66ernaut

Le gestionnaire d'erreurs, le deuxième paramètre, est-il toujours facultatif?
1,21 gigawatts le

C'est de loin la meilleure réponse que j'ai vue jusqu'à présent!
Imam Bux

78

La fonction then () est liée aux "promesses Javascript" qui sont utilisées dans certaines bibliothèques ou frameworks comme jQuery ou AngularJS.

Une promesse est un modèle de gestion des opérations asynchrones. La promesse vous permet d'appeler une méthode appelée "alors" qui vous permet de spécifier la ou les fonctions à utiliser comme rappels.

Pour plus d'informations, voir: http://wildermuth.com/2013/8/3/JavaScript_Promises

Et pour les promesses angulaires: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/


4
c'est donc comme un rappel qui s'exécute quand la tâche est terminée? En quoi est-ce différent
Muhammad Umer

3
les promesses JavaScript dans l'autre commentaire disent:, A promise can only succeed or fail onceetIf a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called
Xiao

En outre, les pépites Promise expliquent comment utiliser promiseet ce qui serait fait aveccallback
Xiao

Sur la première page, il manque des morceaux de code (gros blancs blancs). La plupart des gens penseront à inspecter l'élément et trouveront les URL du violon en dessous. Ce message est pour le reste - les violons fonctionnent toujours;)
DanteTheSmith

1
@MuhammadUmer: lisez ce stackoverflow.com/a/31453579/1350476 (réponse de Sid)
SharpCoder

32

À ma connaissance, il n'y a pas de then()méthode intégrée dans javascript(au moment d'écrire ces lignes).

Il semble que tout ce qui doSome("task")retourne a une méthode appelée then.

Si vous enregistrez le résultat du retour de doSome()dans la console, vous devriez pouvoir voir les propriétés de ce qui a été retourné.

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

MISE À JOUR (à partir d'ECMAScript6) : -

La .then()fonction a été incluse en javascript pur.

De la documentation de Mozilla ici ,

La méthode then () renvoie une promesse. Il prend deux arguments: des fonctions de rappel pour les cas de réussite et d'échec de la promesse.

L'objet Promise, à son tour, est défini comme

L'objet Promise est utilisé pour les calculs différés et asynchrones. Une promesse représente une opération qui n'est pas encore terminée, mais qui est attendue à l'avenir.

Autrement dit, les Promiseactes comme un espace réservé pour une valeur qui n'est pas encore calculée, mais doit être résolu à l'avenir. Et la .then()fonction est utilisée pour associer les fonctions à invoquer sur la Promesse lorsqu'elle est résolue - soit comme un succès, soit comme un échec.


12
Il n'y avait pas de système intégré à l' .thenépoque, mais les promesses natives arrivent maintenant dans ES6: html5rocks.com/en/tutorials/es6/promises
janfoeh

merci pour cette réponse, je m'attendais à un rappel de promesse sympa, mais il s'est avéré être une fonction réelle appelée «alors» qui a été renvoyée.
spartikus

15

Voici une chose que je me suis faite pour clarifier comment les choses fonctionnent. Je suppose que d'autres aussi peuvent trouver cet exemple concret utile:

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>


5

Voici un petit JS_Fiddle.

est ensuite une pile de rappel de méthode qui est disponible après qu'une promesse est résolue, elle fait partie d'une bibliothèque comme jQuery mais maintenant elle est disponible en JavaScript natif et ci-dessous est l'explication détaillée de son fonctionnement

Vous pouvez faire une promesse en JavaScript natif: tout comme il y a des promesses dans jQuery, chaque promesse peut être empilée, puis peut être appelée avec les rappels Resolve et Reject, c'est ainsi que vous pouvez chaîner des appels asynchrones.

J'ai bifurqué et édité à partir de MSDN Docs sur l'état de charge de la batterie.

Cela consiste à essayer de savoir si l'ordinateur portable ou l'appareil de l'utilisateur charge la batterie. est ensuite appelé et vous pouvez faire votre travail après le succès.

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

Un autre exemple es6

function fetchAsync (url, timeout, onData, onError) {
    
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})

Definition :: then est une méthode utilisée pour résoudre les rappels asynchrones

ceci est introduit dans ES6

Veuillez trouver la documentation appropriée ici Es6 Promises


Votre réponse ne répond pas réellement à la question. Il ne fournit qu'un exemple de l'utilisation de l'API sans expliquer d'où thenvient et comment cela fonctionne. Vous devriez améliorer votre réponse pour fournir ces détails.
Didier L

@TarandeepSingh - dans la première déclaration, puis dans laquelle vous avertissez l'état de la batterie, aucun objet promis n'est renvoyé. Alors à quoi sert la seconde alors
Mohit Jain

@MohitJain It vous montre que vous pouvez effectuer plusieurs rappels même si vous n'avez aucune nouvelle promesse. Depuis, les appels multiples pourraient également être effectués avec Promise.all.
Tarandeep Singh

Que voulez-vous dire par « pile de rappel de méthode »?
Bergi

4

Je soupçonne que doSome renvoie ceci, qui est myObj, qui a également une méthode then. Chaînage de méthode standard ...

si doSome ne retourne pas ceci, étant l'objet sur lequel doSome a été exécuté, soyez assuré qu'il retourne un objet avec une méthode then ...

comme le souligne @patrick, il n'y a pas alors () pour les js standard


1
Je soupçonne doSome de rendre cela - rien n'impose / ne justifie de telles suspensions
Salathiel Genèse

1

doSome ("tâche") doit renvoyer un objet de promesse, et cette promesse a toujours une fonction then. Donc, votre code est comme ça

promise.then(function(env) {
    // logic
}); 

et vous savez que c'est juste un appel ordinaire à la fonction membre.


1

.then renvoie une promesse dans la fonction asynchrone.

Un bon exemple serait:

var doSome = new Promise(function(resolve, reject){
    resolve('I am doing something');
});

doSome.then(function(value){
    console.log(value);
});

Pour lui ajouter une autre logique, vous pouvez également ajouter l' reject('I am the rejected param')appel la fonction et la console.log.


0

Dans ce cas, then()est une méthode de classe de l'objet retourné par la doSome()méthode.


0

La fonction ".then ()" est largement utilisée pour les objets promis dans la programmation Asynchoronus pour les applications du Windows 8 Store. Pour autant que j'ai compris, cela fonctionne d'une certaine manière comme un rappel.

Trouvez des détails dans cette Documentantion http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

Cela peut également être le nom de toute autre fonction définie.


0

Un autre exemple:

new Promise(function(ok) {
   ok( 
      /* myFunc1(param1, param2, ..) */
   )
}).then(function(){
     /* myFunc1 succeed */
     /* Launch something else */
     /* console.log(whateverparam1) */
     /* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
     /* myFunc2 succeed */
     /* Launch something else */
     /* myFunc3(whatever38, ..) */
})

La même logique en utilisant les fonctions flèches:

new Promise((ok) =>
   ok( 
      /* myFunc1(param1, param2, ..) */
)).then(() =>
     /* myFunc1 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc2(whateverparam1, otherparam, ..) */
).then(() =>
     /* myFunc2 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc3(whatever38, ..) */
)


-4

J'ai environ 8 ans de retard, eh bien ... de toute façon, je ne sais pas vraiment ce que fait alors () mais peut-être que MDN pourrait avoir une réponse. En fait, je pourrais peut-être le comprendre un peu plus.

Cela vous montrera toutes les informations (espérons-le) dont vous avez besoin. Sauf si quelqu'un a déjà publié ce lien. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Le format est promise.prototype.then () La promesse et le prototype sont un peu comme des variables mais pas comme des variables en javascript, je veux dire comme d'autres choses y vont comme navigator.getBattery (). Then () où celle-ci existe réellement mais est à peine utilisé sur le web, celui-ci affiche les statuts de la batterie de l'appareil, plus d'informations et plus sur MDN si vous êtes curieux.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.