Angular HttpPromise: różnica między metodami „sukces” / „błąd” a argumentami argumentów „then”

177

Zgodnie z dokumentem AngularJS wezwania do $httpzwrotu następujących elementów:

Zwraca obiekt obietnicy ze standardową metodą then i dwiema metodami specyficznymi dla http: sukces i błąd . Metoda then przyjmuje dwa argumenty jako sukces i wywołanie zwrotne błędu, które zostanie wywołane z obiektem odpowiedzi. Metody sukcesu i błędu pobierają jeden argument - funkcję, która zostanie wywołana, gdy żądanie zakończy się sukcesem lub niepowodzeniem. Argumenty przekazane do tych funkcji są zniszczoną reprezentacją obiektu odpowiedzi przekazanego do metody then.

Pomijając fakt, że responseobiekt jest zniszczony w jednym przypadku, nie widzę różnicy między

  • powodzenie / błąd wywołania zwrotne przekazane do przekazania jako argumenty programu promise.then
  • wywołania zwrotne przekazane jako argumenty metod promise.success/ promise.errorobietnicy

Czy jest jakiś? Jaki jest sens tych dwóch różnych sposobów przekazywania pozornie identycznych wywołań zwrotnych?

ejoubaud
źródło

Odpowiedzi:

156

Uwaga: ta odpowiedź jest nieprawidłowa; jak wskazano w komentarzu poniżej, success () zwraca pierwotną obietnicę. Nie zmienię się; i pozostaw to OP do edycji.


Główną różnicą między 2 jest to, że .then()call zwraca obietnicę (rozwiązaną z wartością zwróconą z callback), podczas gdy .success()jest bardziej tradycyjnym sposobem rejestrowania callbacków i nie zwraca obietnicy.

Oparte na obietnicach wywołania zwrotne ( .then()) ułatwiają łączenie obietnic (wykonaj wywołanie, zinterpretuj wyniki, a następnie wykonaj kolejne wywołanie, zinterpretuj wyniki, wykonaj jeszcze jedno wywołanie itp.).

Ta .success()metoda jest usprawnioną, wygodną metodą, gdy nie musisz łączyć połączeń łańcuchowych ani pracować z obiecującym interfejsem API (na przykład w routingu).

W skrócie:

  • .then() - pełna moc obiecującego API, ale nieco bardziej szczegółowe
  • .success() - nie zwraca obietnicy, ale oferuje nieco wygodniejszą składnię
pkozlowski.opensource
źródło
44
Kolejną dużą różnicą jest to, że thenwywołania zwrotne ma jeden argument - odpowiedź - podczas successi errorwziąć poszczególnych składników odpowiedzi jako arguments-- data, status, header, i config.
Michelle Tilley
1
@BrandonTilley całkowicie w porządku, ale autor pytania już to rozgryzł, więc nie czułem, że muszę to tutaj powtarzać.
pkozlowski.opensource
45
Chociaż dokumentacja nie mówi tego wprost, możemy wywnioskować, że .success()metoda zwraca oryginalny obiekt obietnicy $ http, ponieważ łańcuch $http(...).success(...).error(...)jest możliwy. Jeśli, co wydaje się rozsądne, odwrotność $http(...).error(...).success(...)jest również możliwa, .error()należy również zwrócić oryginalny obiekt obietnicy. Różnica .then()polega na tym, że zwraca nową obietnicę.
Burak-Burak
2
Kod źródłowy z angular.js usługi $ http:promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che
6
Pamiętaj, że successzostał wycofany. Od 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

Jest tu już kilka dobrych odpowiedzi. Ale warto wyjaśnić różnicę w oferowanej równoległości:

  • success() zwraca pierwotną obietnicę
  • then() zwraca nową obietnicę

Różnica polega na then()sterowaniu sekwencyjnymi operacjami, ponieważ każde wywołanie zwraca nową obietnicę.

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

success() steruje operacjami równoległymi, ponieważ programy obsługi są połączone łańcuchami według tej samej obietnicy.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()Równolegle
event_jr
źródło
3
Zwróć uwagę, że nowa odpowiedź dotycząca obietnicy zwrócona po thenosiągnięciu a powoduje zniknięcie metod successi error. Również dla http reakcje na błędy (np 404) pierwszy thenw http.then(ok, err).then(ok, err)przejdzie do errobsługi, ale następujące z nich przejdzie do okobsługi. Zasadniczo http.success().error().success().error()można łączyć w łańcuchy, ale obietnice $ q są zupełnie inne, ponieważ dotyczą obietnic i konkretnej kolejności obsługi (a nie obsługi żądań http). Trudno mi było to zrozumieć, dopóki nie przyjrzałem się bliżej.
Jimmont
1
@jimmont successi errornie są normalnym API obietnicy, są przykręcone do zwracanej wartości $ http ().
event_jr
Dzięki @event_jr to jest dla mnie jasne i zawołałem w dokumentacji. To, co nie było dla mnie tak jasne, to jak $ q i $ http rozwiązują różne problemy, a także zwracają nowe obietnice, a nie przekazują te same - jak wskazano w Twojej (bardzo pomocnej) odpowiedzi.
jimmont,
1
Co masz na myśli mówiąc równolegle, skoro JS jest jednowątkowy? Masz na myśli, że zlecenie wykonania jest niedeterministyczne?
Derek
2
@Derek drugi successwykona się po wykonaniu pierwszego, ale zanim zwrócona z niego obietnica zostanie rozwiązana, podczas gdy druga thenbędzie czekać. Jeśli nie składasz obietnic, oboje zachowują się tak samo.
Tamlyn
114

Kilka przykładów kodu dla prostego żądania GET. Może to pomoże zrozumieć różnicę. Używając 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
});

Używanie success/ error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
TheHippo
źródło
5
Dziękuję, ale pytanie dotyczyło bardziej różnicy w działaniu tych funkcji lub powodu, dla którego obie istnieją, jeśli robią to samo. Różnica w sposobie ich używania jest zrozumiała na podstawie dokumentu.
ejoubaud
39
Osobiście lubię krótkie przykłady kodu i właśnie je tutaj zamieściłem. W dokumentach Angulara czasami brakuje krótkich, precyzyjnych przykładów.
TheHippo
2
Należy podkreślić fakt, że obiekt odpowiedzi pierwszej istoty zawiera „dane, stan, heade i konfigurację” drugiej istoty. Oznacza to, że obiekty reagujące mają jeden poziom dodatkowej głębokości.
geoom
Czy jest jakaś korzyść z przekazywania wartości odpowiedzi do zmiennych w data,status,header,configporównaniu z prostym zwracaniem response?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
27

.then () można łączyć w łańcuch i będzie czekać na rozwiązanie metody previousthen ().

.success () i .error () mogą być połączone łańcuchami, ale wszystkie będą odpalać naraz (więc niewiele na to wskazuje)

.success () i .error () są po prostu przydatne w przypadku prostych wywołań (łatwe twórcy):

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

więc nie musisz wpisywać tego:

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

Ale generalnie obsługuję wszystkie błędy za pomocą .catch ():

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

Jeśli potrzebujesz obsługiwać <= IE8, napisz swoje .catch () i .finally () w ten sposób (metody zastrzeżone w IE):

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

Przykłady robocze:

Oto coś, co napisałem w bardziej kodowym formacie, aby odświeżyć pamięć, jak to wszystko wygląda z obsługą błędów itp:

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

nawlbergs
źródło
Jedyna odpowiedź, która pokazuje, jak działa funkcja „return-another-obietnica”
zjk
17

Dla uzupełnienia, oto przykład kodu wskazujący różnice:

sukces \ błąd:

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

następnie:

$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
źródło
świetnie !, czy masz przykład, w którym konkatenacja może być przydatna?
geoom
4
Chodzi o to, że podejście „wtedy” jest bardziej przydatne, ponieważ można łatwiej zapisywać operacje asynchroniczne jedna po drugiej.
MichaelLo
2

Oficjalna uwaga: sukces i błąd zostały wycofane. Zamiast tego użyj standardowej metody then.

Powiadomienie o wycofaniu: Sukces i błąd starszych metod obietnicy $ http zostały wycofane. Zamiast tego użyj metody standard then. Jeśli $ httpProvider.useLegacyPromiseExtensions ma wartość false, te metody będą zgłaszać błąd $ http / legacy.

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

zrzut ekranu: wyświetl zrzut ekranu

MagicBoy
źródło