Angular HttpPromise: differenza tra i metodi `success` /` error` e gli argomenti `then`


177

Secondo il documento AngularJS , chiama per $httprestituire quanto segue:

Restituisce un oggetto promessa con il metodo standard then e due metodi specifici http: successo ed errore . Il metodo then accetta due argomenti con esito positivo e un callback di errore che verrà chiamato con un oggetto response. I metodi di successo ed errore accettano un singolo argomento: una funzione che verrà chiamata quando la richiesta ha esito positivo o negativo. Gli argomenti passati a queste funzioni sono rappresentazioni destrutturate dell'oggetto di risposta passato al metodo then.

A parte il fatto che l' responseoggetto è destrutturato in un caso, non capisco la differenza tra

  • i callback di successo / errore passati per essere passati come argomenti di promise.then
  • i callback sono passati come argomenti per i metodi promise.success/ promise.errordella promessa

C'è qualche? Qual è il punto di questi due modi diversi di passare callback apparentemente identici?

Risposte:


156

NB Questa risposta è in realtà errata; come sottolineato da un commento qui sotto, success () restituisce la promessa originale. Non cambierò; e lasciarlo su OP per modificarlo.


La differenza principale tra i 2 è che la .then()chiamata restituisce una promessa (risolta con un valore restituito da una richiamata) mentre .success()è il modo più tradizionale di registrare le richiamate e non restituisce una promessa.

I callback basati su promesse ( .then()) facilitano il concatenamento di promesse (effettuare una chiamata, interpretare i risultati e quindi fare un'altra chiamata, interpretare i risultati, fare ancora un'altra chiamata ecc.).

Il .success()metodo è un metodo semplificato e conveniente quando non è necessario eseguire la chiamata in serie o lavorare con l'API promessa (ad esempio, nel routing).

In breve:

  • .then() - piena potenza dell'API promessa ma leggermente più dettagliata
  • .success() - non restituisce una promessa ma offre una sintassi leggermente più comoda

44
Un'altra grande differenza è che i thencallback prendere un singolo argomento - la risposta - mentre successe errorprendere i singoli componenti della risposta come arguments-- data, status, header, e config.
Michelle Tilley,

1
@BrandonTilley ha perfettamente ragione, ma l'autore della domanda l'ha già capito, quindi non mi sentivo di doverlo ripetere qui.
pkozlowski.opensource

45
Sebbene la documentazione non lo dica esplicitamente, possiamo dedurre che il .success()metodo restituisce l'oggetto promessa $ http originale, poiché la catena $http(...).success(...).error(...)è possibile. Se, come sembra ragionevole, $http(...).error(...).success(...)è anche possibile l'inverso , allora .error()dovrebbe anche restituire l'oggetto promessa originale. La differenza distintiva di .then()è che restituisce una nuova promessa.
Beetroot-Beetroot

2
Codice sorgente da angular.js del servizio $ http: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che il

6
Si noti che successè stato deprecato. Da 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

Ci sono già alcune buone risposte qui. Ma vale la pena portare a casa la differenza di parallelismo offerta:

  • success() restituisce la promessa originale
  • then() restituisce una nuova promessa

La differenza sta nelle then()operazioni sequenziali, poiché ogni chiamata restituisce una nuova promessa.

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

success() guida operazioni parallele, poiché i gestori sono incatenati sulla stessa promessa.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()in parallelo

3
Si noti la nuova risposta promessa tornato una volta al thenraggiungimento dei risultati nel successe errormetodi di scomparire. Inoltre, per le risposte agli errori http (ad es. 404), il primo thenin http.then(ok, err).then(ok, err)passerà al errgestore, ma quelli seguenti passeranno al okgestore. Fondamentalmente http.success().error().success().error()sono concatenabili, ma le promesse di $ q sono piuttosto diverse in quanto riguardano interamente la promessa e la sequenza di gestione specifica (e non la gestione delle richieste http). Ho avuto difficoltà a capirlo fino a quando non ho dato un'occhiata da vicino.
Jimmont,

1
@jimmont successe errornon sono normali API di una promessa, sono fissati al valore di ritorno di $ http ().
event_jr

Grazie a @event_jr, questo mi è chiaro e mi ha richiamato nei documenti. Ciò che non è stato chiaro (per me) è come $ q e $ http risolvono diversi problemi, oltre a restituire nuove promesse rispetto a passare la stessa attraverso - come sottolineato nella risposta (super utile).
Jimmont,

1
Cosa intendi per parallelo, dal momento che JS è a thread singolo? Vuoi dire che l'ordine di esecuzione non è deterministico?
Derek,

2
@Derek il secondo successverrà eseguito dopo l'esecuzione del primo, ma prima che qualsiasi promessa restituita venga risolta mentre il secondo thenattenderà. Se non stai restituendo promesse, entrambi si comportano allo stesso modo.
Tamlyn,

114

Alcuni esempi di codice per una semplice richiesta GET. Forse questo aiuta a capire la differenza. Utilizzando 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
});

Utilizzando success/ error:

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

5
Grazie, ma la domanda riguardava più la differenza in ciò che fanno queste funzioni o il motivo per cui entrambe esistono se fanno la stessa cosa. La differenza nel modo di usarli è comprensibile dal documento.
ejoubaud,

39
Personalmente mi piacciono gli esempi di codici brevi, e li ho pubblicati qui. I documenti angolari a volte perdono brevi esempi precisi.
TheHippo

2
È importante evidenziare il fatto che l'oggetto di risposta della prima sintesi contiene "dati, stato, heade e config" della seconda sintesi. Ciò significa che gli oggetti response hanno un livello aggiuntivo di profondità.
geoom

C'è qualche vantaggio nel passare i valori di risposta alle variabili data,status,header,configpiuttosto che semplicemente ritornare response?
ʙᴀᴋᴇʀ ʙᴀᴋᴇʀ

27

.then () è concatenabile e attenderà la risoluzione di .then () precedente.

.success () e .error () possono essere concatenati, ma spareranno tutti in una volta (quindi non indicano molto)

.success () e .error () sono perfetti per le chiamate semplici (easy maker):

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

quindi non è necessario digitare questo:

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

Ma generalmente gestisco tutti gli errori con .catch ():

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

Se è necessario supportare <= IE8, scrivere in questo modo .catch () e .finally () in questo modo (metodi riservati in IE):

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

Esempi di lavoro:

Ecco qualcosa che ho scritto in un formato più codey per rinfrescare la mia memoria su come tutto funziona con errori di gestione ecc:

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


L'unica risposta che mostra come funziona il "ritorno-un'altra-promessa"
zjk

17

Solo per il completamento, ecco un esempio di codice che indica le differenze:

successo \ errore:

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

poi:

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

grande !, hai un esempio in cui la concatenazione può essere utile?
geoom

4
L'idea è che l'approccio "then" sia più utile, poiché è possibile scrivere più facilmente operazioni asincrone una dopo l'altra.
Michael,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.