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?

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ę

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

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

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/


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

ś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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.