La gestion de jQuery.ajax continue les réponses: «succès:» vs «.done»?

309

Je travaille avec jQuery et AJAX depuis quelques semaines et j'ai vu deux façons différentes de «continuer» le script une fois l'appel effectué: success:et .done.

Extrait du synopsis du documentation jQuery nous obtenons:

.done (): Description: Ajoutez des gestionnaires à appeler lorsque l'objet différé est résolu.

success: (option .ajax ()): fonction à appeler si la requête aboutit.

Donc, les deux font quelque chose une fois l'appel AJAX terminé / résolu. Puis-je utiliser l'un ou l'autre au hasard? Quelle est la différence et quand l'un est utilisé à la place de l'autre?

Claudio
la source

Réponses:

469

successa été le nom traditionnel du rappel de réussite dans jQuery, défini comme une option dans l'appel ajax. Cependant, depuis l'implémentation de $.Deferredsrappels plus sophistiqués, donec'est le moyen préféré pour implémenter des rappels réussis, car il peut être appelé sur n'importe quel deferred.

Par exemple, le succès:

$.ajax({
  url: '/',
  success: function(data) {}
});

Par exemple, fait:

$.ajax({url: '/'}).done(function(data) {});

Ce qui est bien, donec'est que la valeur de retour de $.ajaxest désormais une promesse différée qui peut être liée à n'importe où ailleurs dans votre application. Supposons donc que vous souhaitiez effectuer cet appel ajax à partir de plusieurs endroits différents. Plutôt que de passer dans votre fonction de succès en option à la fonction qui rend cet appel ajax, vous pouvez juste avoir le retour de la fonction $.ajaxelle - même et se lient vos callbacks avec done, fail, thenou autre chose. Notez qu'il alwayss'agit d'un rappel qui s'exécutera si la demande réussit ou échoue. donene sera déclenché qu'en cas de succès.

Par exemple:

function xhr_get(url) {

  return $.ajax({
    url: url,
    type: 'get',
    dataType: 'json',
    beforeSend: showLoadingImgFn
  })
  .always(function() {
    // remove loading image maybe
  })
  .fail(function() {
    // handle request failures
  });

}

xhr_get('/index').done(function(data) {
  // do stuff with index data
});

xhr_get('/id').done(function(data) {
  // do stuff with id data
});

Un avantage important de ceci en termes de maintenabilité est que vous avez enveloppé votre mécanisme ajax dans une fonction spécifique à l'application. Si vous décidez que votre $.ajaxappel devra fonctionner différemment à l'avenir, ou si vous utilisez une méthode ajax différente, ou si vous vous éloignez de jQuery, vous n'avez qu'à modifier la xhr_getdéfinition (en étant sûr de renvoyer une promesse ou au moins une doneméthode, dans le cas de l'exemple ci-dessus). Toutes les autres références dans l'application peuvent rester les mêmes.

Il y a beaucoup plus (beaucoup plus cool) de choses que vous pouvez faire $.Deferred, dont l'une consiste pipeà déclencher une défaillance sur une erreur signalée par le serveur, même lorsque la $.ajaxdemande elle-même réussit. Par exemple:

function xhr_get(url) {

  return $.ajax({
    url: url,
    type: 'get',
    dataType: 'json'
  })
  .pipe(function(data) {
    return data.responseCode != 200 ?
      $.Deferred().reject( data ) :
      data;
  })
  .fail(function(data) {
    if ( data.responseCode )
      console.log( data.responseCode );
  });
}

xhr_get('/index').done(function(data) {
  // will not run if json returned from ajax has responseCode other than 200
});

En savoir plus sur $.Deferredici: http://api.jquery.com/category/deferred-object/

REMARQUE : à partir de jQuery 1.8, pipea été déconseillé au profit de l'utilisation thenexactement de la même manière.

glortho
la source
2
Je me demande comment les interactions de success:/ .done()sont définies, le cas échéant. Par exemple, est success:juste mis en œuvre comme le premier .done()ces jours-ci?
6
Vous voulez dire que si vous avez les deux success:et .doneun appel ajax? Bonne question. Étant donné que tous les autres rappels sont appelés dans l'ordre dans lequel ils sont liés, je suppose que oui, successest simplement appelé en premier.
glortho
1
Très beau post! Btw, dans le rappel de tuyau, ne devriez-vous pas appeler la fonction de tuyau avec le paramètre jqXHR afin de vérifier la réponse d'état? Ex: .pipe (fonction (data, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder
@Eder Le scénario que j'aborde avec cette utilisation pipeest celui où la demande elle-même réussit mais le script sur le serveur n'a pas retourné ce que vous cherchiez. Vous ne voudrez peut-être pas jeter un 404 ou 500 réel ou autre côté serveur, car vous voulez faire une distinction significative entre les réponses http et les réponses des applications. La définition d'un code de réponse dans le JSON, puis l'utilisation de pipecette manière vous permet de gérer différents types d'erreurs avec plus de nuances.
glortho
Un autre avantage important de l'utilisation des promesses est que votre code devient beaucoup plus lisible et que vous évitez «l'enfer de rappel». Cela est particulièrement vrai lorsque vous avez plusieurs rappels que vous souhaitez exécuter chacun après la précédente. Avec des promesses, cela ressemblerait à myPromiseCall.then (..). Then (..) au lieu d'une structure compliquée imbriquée de rappels utilisée avec l'option success.
BornToCode
5

Si vous async: falseen avez besoin dans votre ajax, vous devez utiliser à la successplace de .done. Sinon, il vaut mieux utiliser .done. C'est du site officiel de jQuery :

Depuis jQuery 1.8, l'utilisation de async: false avec jqXHR ($ .Deferred) est déconseillée; vous devez utiliser les options de rappel succès / erreur / complet au lieu des méthodes correspondantes de l'objet jqXHR telles que jqXHR.done () .

AmirHossein Manian
la source
Qui mentionne async:false?
Liam
$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian
0

Depuis la documentation JQuery

Les objets jqXHR renvoyés par $.ajax()jQuery 1.5 implémentent l'interface Promise, en leur donnant toutes les propriétés, méthodes et comportement d'une promesse (voir Objet Deferred pour plus d'informations). Ces méthodes prennent un ou plusieurs arguments de fonction qui sont appelés lorsque la $.ajax()demande se termine. Cela vous permet d'affecter plusieurs rappels sur une seule demande, et même d'attribuer des rappels une fois la demande terminée. (Si la demande est déjà terminée, le rappel est déclenché immédiatement.) Les méthodes Promise disponibles de l'objet jqXHR incluent:

jqXHR.done(function( data, textStatus, jqXHR ) {});

Une construction alternative à l'option de rappel de réussite, reportez-vous à deferred.done()pour les détails d'implémentation.

jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});

Une construction alternative à l'option de rappel d'erreur, la .fail()méthode remplace la méthode .error () obsolète. Reportez-vous à deferred.fail () pour les détails d'implémentation.

jqXHR.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) { }); 

(ajouté dans jQuery 1.6) Une construction alternative à l'option de rappel complet, la .always()méthode remplace la .complete()méthode déconseillée .

En réponse à une requête réussie, les arguments de la fonction sont les mêmes que ceux de .done(): data, textStatus et l'objet jqXHR. Pour les requêtes ayant échoué, les arguments sont les mêmes que ceux de .fail(): l'objet jqXHR, textStatus et errorThrown. Reportez-vous à deferred.always()pour les détails d'implémentation.

jqXHR.then(function( data, textStatus, jqXHR ) {}, function( jqXHR, textStatus, errorThrown ) {});

Intègre la fonctionnalité des méthodes .done()et .fail(), permettant (à partir de jQuery 1.8) de manipuler la promesse sous-jacente. Reportez-vous à différé .then()pour les détails de mise en œuvre.

Obsolescence Avis: Le jqXHR.success(), jqXHR.error()et jqXHR.complete()callbacks sont supprimés à partir de jQuery 3.0. Vous pouvez utiliser jqXHR.done(), jqXHR.fail()et à la jqXHR.always()place.

Sasmit
la source