jQuery.ajax-Behandlung Antworten fortsetzen: "Erfolg:" vs ".done"?

309

Ich arbeite jetzt seit einigen Wochen mit jQuery und AJAX und habe zwei verschiedene Möglichkeiten gesehen, das Skript nach dem Aufruf fortzusetzen: success:und .done.

Aus der Zusammenfassung der jQuery-Dokumentation erhalten wir:

.done (): Beschreibung: Fügen Sie Handler hinzu, die aufgerufen werden sollen, wenn das verzögerte Objekt aufgelöst wird.

Erfolg: (Option .ajax ()): Eine Funktion, die aufgerufen werden soll, wenn die Anforderung erfolgreich ist.

Beide tun also etwas, nachdem der AJAX-Aufruf abgeschlossen / aufgelöst wurde. Kann ich das eine oder andere zufällig verwenden? Was ist der Unterschied und wann wird einer anstelle des anderen verwendet?

Claudio
quelle

Antworten:

469

successwar der traditionelle Name des Erfolgsrückrufs in jQuery, der als Option im Ajax-Aufruf definiert wurde. Da jedoch die Implementierung $.Deferredsund komplexere Rückrufe doneder bevorzugte Weg ist, um erfolgreiche Rückrufe zu implementieren, wie sie bei jedem aufgerufen werden können deferred.

Zum Beispiel Erfolg:

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

Zum Beispiel erledigt:

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

Das Schöne daran doneist, dass der Rückgabewert von $.ajaxjetzt ein aufgeschobenes Versprechen ist, das an eine andere Stelle in Ihrer Anwendung gebunden werden kann. Nehmen wir also an, Sie möchten diesen Ajax-Anruf von verschiedenen Orten aus tätigen. Anstatt Ihre Erfolgsfunktion als Option an die Funktion zu übergeben, die diesen Ajax-Aufruf ausführt, können Sie einfach die Funktion zurückgeben lassen$.ajax selbst und binden Sie Ihre Rückrufe mit done, fail, then, oder was auch immer. Beachten Sie, dass dies alwaysein Rückruf ist, der ausgeführt wird, unabhängig davon, ob die Anforderung erfolgreich ist oder fehlschlägt. donewird nur bei Erfolg ausgelöst.

Zum Beispiel:

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
});

Ein wichtiger Vorteil in Bezug auf die Wartbarkeit besteht darin, dass Sie Ihren Ajax-Mechanismus in eine anwendungsspezifische Funktion eingebunden haben. Wenn Sie sich entscheiden, brauchen Sie Ihre$.ajax Anruf in Zukunft anders funktionieren soll, oder wenn Sie eine andere Ajax-Methode verwenden oder sich von jQuery entfernen, müssen Sie nur die xhr_getDefinition ändern (stellen Sie sicher, dass Sie ein Versprechen oder zumindest eine doneMethode zurückgeben) der Fall des obigen Beispiels). Alle anderen Referenzen in der App können gleich bleiben.

Es gibt viel mehr (viel coolere) Dinge, die Sie tun $.Deferredkönnen. Eine davon ist, pipeeinen Fehler bei einem vom Server gemeldeten Fehler auszulösen, selbst wenn der$.ajax Anforderung selbst erfolgreich ist . Zum Beispiel:

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
});

Lesen Sie mehr über $.Deferred : http://api.jquery.com/category/deferred-object/

HINWEIS : Ab jQuery 1.8 wurde pipedie Verwendung thenauf genau die gleiche Weise abgelehnt .

glortho
quelle
2
Ich frage mich, wie die Interaktionen von success:/ .done()definiert sind, wenn überhaupt. ZB wird heutzutage success:nur als erstes implementiert .done()?
6
Du meinst, wenn du beides hast success:und .doneeinen Ajax-Anruf hast ? Gute Frage. Da alle anderen Rückrufe in der Reihenfolge aufgerufen werden, in der sie gebunden sind, ist meine Vermutung ja, successwird nur zuerst aufgerufen.
Glortho
1
Sehr schöner Beitrag! Übrigens, sollten Sie im Pipe-Rückruf nicht die Pipe-Funktion mit dem Parameter jqXHR aufrufen, um nach Statusantworten zu suchen? Beispiel: .pipe (Funktion (Daten, TextStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder
@Eder Das Szenario, das ich mit dieser Verwendung anspreche, pipeist eines, bei dem die Anforderung selbst erfolgreich ist, das Skript auf dem Server jedoch nicht das zurückgegeben hat, wonach Sie gesucht haben. Möglicherweise möchten Sie keine tatsächlichen 404 oder 500 oder was auch immer auf die Serverseite werfen, da Sie sinnvoll zwischen http-Antworten und Anwendungsantworten unterscheiden möchten. Wenn Sie einen Antwortcode in JSON festlegen und dann auf pipediese Weise verwenden, können Sie verschiedene Arten von Fehlern nuancierter behandeln.
Glortho
Ein weiterer wichtiger Vorteil der Verwendung von Versprechungen besteht darin, dass Ihr Code viel besser lesbar wird und Sie die "Rückruf-Hölle" vermeiden. Dies gilt insbesondere dann, wenn Sie mehrere Rückrufe haben, die Sie nach dem vorherigen Abschluss ausführen möchten. Mit Versprechungen würde es wie myPromiseCall.then (..). Then (..) aussehen, anstatt eine verschachtelte komplizierte Struktur von Rückrufen, die mit der Erfolgsoption verwendet werden.
BornToCode
5

Wenn Sie async: falsein Ihrem Ajax benötigen , sollten Sie successanstelle von verwenden .done. Sonst bist du besser zu benutzen .done. Dies ist von der offiziellen jQuery-Website :

Ab jQuery 1.8 ist die Verwendung von async: false mit jqXHR ($ .Deferred) veraltet. Sie müssen die Verwendung Erfolg / Fehler / complete Rückrufoptionen statt die entsprechenden Methoden des jqXHR Objekt wie jqXHR.done () .

AmirHossein Manian
quelle
Wer erwähnt async:false?
Liam
$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian
0

Aus der JQuery-Dokumentation

Die ab $.ajax()jQuery 1.5 zurückgegebenen jqXHR-Objekte implementieren die Promise-Schnittstelle und geben ihnen alle Eigenschaften, Methoden und das Verhalten eines Promise ( weitere Informationen finden Sie unter Zurückgestelltes Objekt ). Diese Methoden verwenden ein oder mehrere Funktionsargumente, die beim $.ajax()Beenden der Anforderung aufgerufen werden . Auf diese Weise können Sie einer einzelnen Anforderung mehrere Rückrufe zuweisen und sogar Rückrufe zuweisen, nachdem die Anforderung möglicherweise abgeschlossen wurde. (Wenn die Anforderung bereits abgeschlossen ist, wird der Rückruf sofort ausgelöst.) Zu den verfügbaren Promise-Methoden des jqXHR-Objekts gehören:

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

Ein alternatives Konstrukt zur Option deferred.done()für einen erfolgreichen Rückruf finden Sie in den Implementierungsdetails.

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

Als alternatives Konstrukt zur Fehlerrückrufoption .fail()ersetzt die Methode die veraltete .error () -Methode. Einzelheiten zur Implementierung finden Sie unter deferred.fail ().

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

(hinzugefügt in jQuery 1.6) Die .always()Methode ist ein alternatives Konstrukt zur vollständigen Rückrufoption und ersetzt die veraltete .complete()Methode.

Als Antwort auf eine erfolgreiche Anforderung sind die Argumente der Funktion dieselben wie die von .done(): data, textStatus und dem jqXHR-Objekt. Für fehlgeschlagene Anforderungen sind die Argumente dieselben wie die von .fail(): jqXHR object, textStatus und errorThrown. Siehe deferred.always()für Implementierungsdetails.

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

Enthält die Funktionalität der Methoden .done()und .fail(), sodass (ab jQuery 1.8) das zugrunde liegende Versprechen manipuliert werden kann. Siehe latenten .then()für Implementierungsdetails.

Deprecation Hinweis: Die jqXHR.success(), jqXHR.error()und jqXHR.complete()Rückrufe werden als von jQuery 3.0 entfernt. Sie können verwendet werden jqXHR.done(), jqXHR.fail()und jqXHR.always()stattdessen.

Sasmit
quelle