Angular HttpPromise: Unterschied zwischen den Methoden "success" / "error" und den Argumenten von "then"

177

Aufrufe laut AngularJS doc , $httpum Folgendes zurückzugeben:

Gibt ein Versprechen- Objekt mit der Standard- Then- Methode und zwei http-spezifischen Methoden zurück: Erfolg und Fehler . Die then- Methode verwendet zwei Argumente, einen erfolgreichen und einen fehlerhaften Rückruf, die mit einem Antwortobjekt aufgerufen werden. Die Erfolgs- und Fehlermethoden verwenden ein einziges Argument - eine Funktion, die aufgerufen wird, wenn die Anforderung erfolgreich ist oder fehlschlägt. Die an diese Funktionen übergebenen Argumente sind eine destrukturierte Darstellung des an die then-Methode übergebenen Antwortobjekts.

Abgesehen von der Tatsache, dass das responseObjekt in einem Fall zerstört ist, verstehe ich den Unterschied nicht

  • Die übergebenen Erfolgs- / Fehlerrückrufe wurden als Argumente von übergeben promise.then
  • Die Rückrufe wurden als Argumente für die promise.success/ promise.errorMethoden des Versprechens übergeben

Gibt es irgendwelche? Was ist der Sinn dieser beiden unterschiedlichen Möglichkeiten, scheinbar identische Rückrufe weiterzuleiten?

Ejoubaud
quelle

Antworten:

156

NB Diese Antwort ist sachlich falsch. Wie in einem Kommentar unten hervorgehoben, gibt success () das ursprüngliche Versprechen zurück. Ich werde mich nicht ändern; und überlassen Sie es OP zum Bearbeiten.


Der Hauptunterschied zwischen den beiden besteht darin, dass der .then()Anruf ein Versprechen zurückgibt (gelöst mit einem Wert, der von einem Rückruf zurückgegeben wird), während dies .success()eine traditionellere Methode zum Registrieren von Rückrufen ist und kein Versprechen zurückgibt .

Versprechensbasierte Rückrufe ( .then()) erleichtern das Verketten von Versprechungen (einen Anruf tätigen, Ergebnisse interpretieren und dann einen weiteren Anruf tätigen, Ergebnisse interpretieren, einen weiteren Anruf tätigen usw.).

Die .success()Methode ist eine optimierte, bequeme Methode, wenn Sie weder einen Kettenaufruf ausführen noch mit der Versprechen-API arbeiten müssen (z. B. beim Routing).

Zusamenfassend:

  • .then() - volle Leistung der Versprechen-API, aber etwas ausführlicher
  • .success() - gibt kein Versprechen zurück, bietet aber eine etwas praktischere Syntax
pkozlowski.opensource
quelle
44
Ein weiterer großer Unterschied ist , dass die thenRückrufe ein einziges Argument - die Antwort - während successund erroreinzelne Komponenten der Antwort als arguments-- nehmen data, status, header, und config.
Michelle Tilley
1
@BrandonTilley völlig richtig, aber der Autor der Frage hat es bereits herausgefunden, so dass ich nicht das Gefühl hatte, es hier wiederholen zu müssen.
pkozlowski.opensource
45
Obwohl die Dokumentation dies nicht explizit sagt, können wir daraus schließen, dass die .success()Methode das ursprüngliche $ http-Versprechen-Objekt zurückgibt, da die Kette $http(...).success(...).error(...)möglich ist. Wenn, wie vernünftig erscheint, auch die Umkehrung $http(...).error(...).success(...)möglich ist, .error()sollte auch das ursprüngliche Versprechungsobjekt zurückgegeben werden. Der Unterschied .then()besteht darin, dass es ein neues Versprechen zurückgibt .
Rote Beete-Rote Beete
2
Quellcode von angle.js von $ http Service: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che
6
Bitte beachten Sie, dass successdies veraltet ist. Von 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

Hier gibt es bereits einige gute Antworten. Es lohnt sich jedoch, den Unterschied in der angebotenen Parallelität nach Hause zu fahren:

  • success() gibt das ursprüngliche Versprechen zurück
  • then() gibt ein neues Versprechen zurück

Der Unterschied besteht darin then(), dass sequentielle Vorgänge ausgeführt werden, da jeder Anruf ein neues Versprechen zurückgibt.

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

success() treibt parallele Operationen an, da Handler nach dem gleichen Versprechen verkettet sind.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()In parallelen
event_jr
quelle
3
Beachten Sie, dass die neue Versprechen-Antwort, die zurückgegeben wird, sobald a thenerreicht ist, dazu führt, dass die Methoden successund errorverschwinden. Auch für die HTTP - Fehlerantworten (zB 404) , die erste thenin http.then(ok, err).then(ok, err)wird auf die Pass - errHandler aber die folgenden Einsen in den Pass werden okHandler. Grundsätzlich http.success().error().success().error()sind sie verkettbar, aber $ q-Versprechen unterscheiden sich insofern erheblich, als es um das Versprechen und die Reihenfolge der Behandlung speziell geht (und nicht um die Bearbeitung von http-Anfragen). Es fiel mir schwer, das zu verstehen, bis ich genau hinschaute.
Jimmy
1
@jimmont successund errorsind keine normale API eines Versprechens, sie sind mit dem Rückgabewert von $ http () verschraubt.
event_jr
Danke @event_jr, das ist mir klar und wird in den Dokumenten erwähnt. Was (für mich) nicht so klar war, ist, wie $ q und $ http verschiedene Probleme lösen und neue Versprechen zurückgeben, anstatt dasselbe durchzugeben - wie in Ihrer (super hilfreichen) Antwort ausgeführt.
Jimmy
1
Was meinst du mit parallel, da JS Single-Threaded ist? Meinen Sie damit, dass die Ausführungsreihenfolge nicht deterministisch ist?
Derek
2
@Derek Der zweite successwird ausgeführt, nachdem der erste ausgeführt wurde, aber bevor ein von ihm zurückgegebenes Versprechen gelöst wird, während der zweite thenwartet. Wenn Sie keine Versprechen zurückgeben, verhalten sich beide gleich.
Tamlyn
114

Einige Codebeispiele für einfache GET-Anforderungen. Vielleicht hilft dies, den Unterschied zu verstehen. Verwenden von 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
});

Verwenden von success/ error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
TheHippo
quelle
5
Vielen Dank, aber die Frage war mehr über den Unterschied in der Funktionsweise dieser Funktionen oder den Grund, warum beide existieren, wenn sie dasselbe tun. Der Unterschied in der Verwendung ist aus dem Dokument ersichtlich.
Ejoubaud
39
Ich persönlich mag kurze Codebeispiele, und das habe ich hier gepostet. In den Angular-Dokumenten fehlen manchmal kurze, präzise Beispiele.
TheHippo
2
Es ist wichtig hervorzuheben, dass das Antwortobjekt des ersten Inhalts "Daten, Status, Heade und Konfiguration" des zweiten Inhalts enthält. Das bedeutet, dass Antwortobjekte eine zusätzliche Tiefe haben.
Geoom
Gibt es einen Vorteil der Übergabe der Antwortwerte an Variablen data,status,header,configgegenüber der einfachen Rückgabe response?
24 ʙᴀᴋᴇʀ
27

.then () ist verkettbar und wartet auf die Auflösung der vorherigen .then ().

.success () und .error () können verkettet werden, aber sie werden alle auf einmal ausgelöst (also nicht viel darauf hinweisen)

.success () und .error () eignen sich nur für einfache Aufrufe (Easy Maker):

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

Sie müssen dies also nicht eingeben:

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

Aber im Allgemeinen behandle ich alle Fehler mit .catch ():

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

Wenn Sie <= IE8 unterstützen müssen, schreiben Sie Ihre .catch () und .finally () wie folgt (reservierte Methoden im IE):

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

Arbeitsbeispiele:

Hier ist etwas, das ich in einem Code-Format geschrieben habe, um mein Gedächtnis darüber aufzufrischen, wie sich alles mit der Behandlung von Fehlern usw. verhält:

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

Nawlbergs
quelle
Die einzige Antwort, die zeigt, wie das "Return-Another-Versprechen" funktioniert
zjk
17

Zur Vervollständigung hier ein Codebeispiel, das die Unterschiede aufzeigt:

Erfolg \ Fehler:

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

dann:

$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
quelle
großartig!, hast du ein Beispiel, wo die Verkettung nützlich sein kann?
Geoom
4
Die Idee ist, dass der "Dann" -Ansatz nützlicher ist, da Sie asynchrone Operationen einfacher nacheinander schreiben können.
MichaelLo
2

Offizieller Hinweis: Erfolg und Fehler sind veraltet. Verwenden Sie stattdessen die Standard-Then-Methode.

Verfallshinweis: Der Erfolg und Fehler der $ http-Legacy-Versprechungsmethoden ist veraltet. Verwenden Sie stattdessen die Standard-Then-Methode. Wenn $ httpProvider.useLegacyPromiseExtensions auf false gesetzt ist, lösen diese Methoden einen $ http / Legacy-Fehler aus.

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

Screenshot: Screenshot anzeigen

MagicBoy
quelle