Angular HttpPromise: différence entre les méthodes `success` / ʻerror` et les arguments de` then`

177

Selon la documentation AngularJS , les appels pour $httprenvoyer ce qui suit:

Renvoie un objet de promesse avec la méthode standard then et deux méthodes spécifiques http: succès et erreur . La méthode then prend deux arguments un succès et un rappel d' erreur qui sera appelé avec un objet de réponse. Les méthodes de succès et d' erreur prennent un seul argument - une fonction qui sera appelée lorsque la demande réussit ou échoue respectivement. Les arguments passés dans ces fonctions sont une représentation déstructurée de l'objet de réponse transmis à la méthode then.

Mis à part le fait que l' responseobjet est déstructuré dans un cas, je ne comprends pas la différence entre

  • les rappels de succès / erreur passés pour être passés comme arguments de promise.then
  • les callbacks passés en arguments pour les méthodes promise.success/ promise.errorde la promesse

Y a-t-il? Quel est l'intérêt de ces deux façons différentes de passer des rappels apparemment identiques?

ejoubaud
la source

Réponses:

156

NB Cette réponse est factuellement incorrecte; comme indiqué par un commentaire ci-dessous, success () renvoie la promesse d'origine. Je ne changerai pas; et laissez OP pour modifier.


La principale différence entre les 2 est que l' .then()appel renvoie une promesse (résolue avec une valeur renvoyée par un rappel) alors qu'il .success()s'agit d'une manière plus traditionnelle d'enregistrer des rappels et ne renvoie pas de promesse.

Les rappels basés sur les promesses ( .then()) facilitent l'enchaînement des promesses (faire un appel, interpréter les résultats puis faire un autre appel, interpréter les résultats, faire encore un autre appel, etc.).

La .success()méthode est une méthode simplifiée et pratique lorsque vous n'avez pas besoin de chaîner un appel ni de travailler avec l'API de promesse (par exemple, dans le routage).

En bref:

  • .then() - pleine puissance de l'API promise mais légèrement plus verbeuse
  • .success() - ne retourne pas de promesse mais offre une syntaxe légèrement plus pratique
pkozlowski.opensource
la source
44
Une autre grande différence est que les thencallbacks prennent un seul argument - la réponse - tout successet errorprendre des composants individuels de la réponse en arguments-- data, status, headeret config.
Michelle Tilley
1
@BrandonTilley tout à fait raison, mais l'auteur de la question l'a déjà compris, donc je n'ai pas eu envie de la répéter ici.
pkozlowski.opensource
45
Bien que la documentation ne le dise pas explicitement, nous pouvons en déduire que la .success()méthode retourne l'objet de promesse $ http original, car la chaîne $http(...).success(...).error(...)est possible. Si, comme cela semble raisonnable, l'inverse $http(...).error(...).success(...)est également possible, alors .error()devrait également renvoyer l'objet de promesse d'origine. La différence distinctive de .then()est qu'il renvoie une nouvelle promesse.
Beetroot-Beetroot
2
Code source angular.js du service $ http: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che
6
Veuillez noter que cela successest obsolète. De docs.angularjs.org/api/ng/service/$http#deprecation-notice The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
Sam Barnum
204

Il y a déjà de bonnes réponses ici. Mais cela vaut la peine de souligner la différence de parallélisme offerte:

  • success() renvoie la promesse originale
  • then() renvoie une nouvelle promesse

La différence réside dans then()les opérations séquentielles, car chaque appel renvoie une nouvelle promesse.

$http.get(/*...*/).
  then(function seqFunc1(response){/*...*/}).
  then(function seqFunc2(response){/*...*/})
  1. $http.get()
  2. seqFunc1()
  3. seqFunc2()

success() conduit des opérations parallèles, puisque les gestionnaires sont enchaînés sur la même promesse.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()en parallèle
event_jr
la source
3
Notez que la nouvelle réponse de promesse renvoyée une fois que a thenest atteinte entraîne la disparition des méthodes successet error. De plus, pour les réponses d'erreur http (par exemple 404), le premier thenin http.then(ok, err).then(ok, err)passera au errgestionnaire mais les suivants passeront au okgestionnaire. Fondamentalement, ils http.success().error().success().error()peuvent être chaînés mais les promesses $ q sont assez différentes en ce sens qu'elles concernent uniquement la promesse et la séquence de traitement (et non la gestion des requêtes http). J'ai eu du mal à comprendre cela jusqu'à ce que je regarde de près.
jimmont
1
@jimmont successet errorne sont pas des API normales d'une promesse, elles sont boulonnées sur la valeur de retour de $ http ().
event_jr
Merci @event_jr, cela est clair pour moi, et appelé dans la documentation. Ce qui n'était pas aussi clair (pour moi), c'est comment $ q et $ http résolvent différents problèmes et retournent de nouvelles promesses par rapport à la même chose - comme indiqué dans votre réponse (très utile).
jimmont
1
Qu'entendez-vous par parallèle, puisque JS est monothread? Voulez-vous dire que l'ordre d'exécution n'est pas déterministe?
Derek
2
@Derek le second successs'exécutera après l'exécution du premier mais avant que toute promesse renvoyée par lui ne soit résolue alors que le second thenattendra. Si vous ne rendez pas vos promesses, les deux se comportent de la même manière.
Tamlyn
114

Quelques exemples de code pour une simple requête GET. Peut-être que cela aide à comprendre la différence. Utilisation then:

$http.get('/someURL').then(function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // success handler
}, function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // error handler
});

Utilisation de success/ error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
TheHippo
la source
5
Merci, mais la question portait davantage sur la différence entre ce que font ces fonctions ou la raison pour laquelle elles existent toutes les deux si elles font la même chose. La différence dans la façon de les utiliser est compréhensible à partir de la doc.
ejoubaud
39
Personnellement, j'aime les exemples de codes courts, et c'est ce que je les ai postés ici. Les documents Angular manquent parfois de courts exemples précis.
TheHippo
2
Il est important de souligner le fait que l'objet de réponse du premier élément essentiel contient "les données, l'état, l'en-tête et la configuration" du second élément essentiel. Cela signifie que les objets de réponse ont un niveau supplémentaire de profondeur.
geoom
Y a-t-il un avantage à transmettre les valeurs de réponse aux variables data,status,header,configplutôt que de simplement renvoyer response?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
27

.then () est chaînable et attendra la résolution de .then () précédente.

.success () et .error () peuvent être enchaînés, mais ils se déclencheront tous en même temps (donc pas grand chose à cela)

.success () et .error () sont juste bien pour les appels simples (fabricants faciles):

$http.post('/getUser').success(function(user){ 
   ... 
})

donc vous n'avez pas à taper ceci:

$http.post('getUser').then(function(response){
  var user = response.data;
})

Mais généralement, je gère toutes les erreurs avec .catch ():

$http.get(...)
    .then(function(response){ 
      // successHandler
      // do some stuff
      return $http.get('/somethingelse') // get more data
    })
    .then(anotherSuccessHandler)
    .catch(errorHandler)

Si vous avez besoin de prendre en charge <= IE8, écrivez votre .catch () et .finally () comme ceci (méthodes réservées dans IE):

    .then(successHandler)
    ['catch'](errorHandler)

Exemples de travail:

Voici quelque chose que j'ai écrit dans un format plus codé pour rafraîchir ma mémoire sur la façon dont tout se joue avec les erreurs de gestion, etc.

http://jsfiddle.net/nalberg/v95tekz2/

nawlbergs
la source
La seule réponse qui montre comment fonctionne le "retour-une-promesse"
zjk
17

Juste pour terminer, voici un exemple de code indiquant les différences:

succès \ erreur:

$http.get('/someURL')
.success(function(data, status, header, config) {
    // success handler
})
.error(function(data, status, header, config) {
    // error handler
});

puis:

$http.get('/someURL')
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
}).
MichaelLo
la source
super !, avez-vous un exemple où la concaténation peut être utile?
geoom
4
L'idée est que l'approche "alors" est plus utile, car vous pouvez plus facilement écrire des opérations asynchrones les unes après les autres.
MichaelLo
2

Avis officiel: le succès et l'erreur sont obsolètes, veuillez utiliser la méthode standard then à la place.

Avis de dépréciation: Les méthodes de promesse héritées de $ http réussies et erreurs sont devenues obsolètes. Utilisez plutôt la méthode standard alors. Si $ httpProvider.useLegacyPromiseExtensions est défini sur false, ces méthodes génèrent une erreur $ http / legacy.

lien: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

capture d'écran: voir la capture d'écran

MagicBoy
la source