HttpPromise angular: diferencia entre los métodos `success` /` error` y los argumentos de `then`

177

Según el documento de AngularJS , las llamadas $httpdevuelven lo siguiente:

Devuelve un objeto de promesa con el método estándar de entonces y dos métodos específicos http: éxito y error . El método then toma dos argumentos, un éxito y una devolución de llamada de error que se llamará con un objeto de respuesta. Los métodos de éxito y error toman un solo argumento, una función que se llamará cuando la solicitud tenga éxito o falle, respectivamente. Los argumentos pasados ​​a estas funciones son una representación desestructurada del objeto de respuesta pasado al método then.

Aparte del hecho de que el responseobjeto está desestructurado en un caso, no obtengo la diferencia entre

  • las devoluciones de llamada de éxito / error pasadas para pasar como argumentos de promise.then
  • las devoluciones de llamada pasadas como argumentos para los métodos promise.success/ promise.errorde la promesa

¿Hay alguna? ¿Cuál es el punto de estas dos formas diferentes de pasar devoluciones de llamada aparentemente idénticas?

ejoubaud
fuente

Respuestas:

156

NB Esta respuesta es objetivamente incorrecta; Como se señala en un comentario a continuación, success () devuelve la promesa original. No voy a cambiar y déjelo a OP para editar.


La principal diferencia entre los 2 es que la .then()llamada devuelve una promesa (resuelta con un valor devuelto por una devolución de llamada) mientras que .success()es la forma más tradicional de registrar devoluciones de llamada y no devuelve una promesa.

Las devoluciones de llamada basadas .then()en promesas ( ) hacen que sea fácil encadenar promesas (hacer una llamada, interpretar resultados y luego hacer otra llamada, interpretar resultados, hacer otra llamada, etc.).

El .success()método es un método simplificado y conveniente cuando no necesita encadenar llamadas ni trabajar con la API de promesa (por ejemplo, en el enrutamiento).

En breve:

  • .then() - potencia total de la API de promesa pero un poco más detallado
  • .success() - no devuelve una promesa pero ofrece una sintaxis un poco más conveniente
pkozlowski.opensource
fuente
44
Otra gran diferencia es que las thendevoluciones de llamada toman un solo argumento - la respuesta -, mientras que successy errortomar los componentes individuales de la respuesta como arguments-- data, status, header, y config.
Michelle Tilley
1
@BrandonTilley tiene toda la razón, pero el autor de la pregunta ya lo descubrió, así que no sentí que tuviera que repetirlo aquí.
pkozlowski.opensource
45
Aunque la documentación no lo dice explícitamente, podemos inferir que el .success()método devuelve el objeto de promesa $ http original, ya que la cadena $http(...).success(...).error(...)es posible. Si, como parece razonable, lo inverso $http(...).error(...).success(...)también es posible, entonces .error()también debería devolver el objeto de promesa original. La diferencia distintiva de .then()es que devuelve una nueva promesa.
Remolacha-Remolacha
2
Código fuente de angular.js del servicio $ http: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che
66
Tenga en cuenta que successha quedado en desuso. De 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

Ya hay algunas buenas respuestas aquí. Pero vale la pena conducir a casa la diferencia en el paralelismo ofrecido:

  • success() devuelve la promesa original
  • then() devuelve una nueva promesa

La diferencia es que then()impulsa operaciones secuenciales, ya que cada llamada devuelve una nueva promesa.

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

success() impulsa operaciones paralelas, ya que los manejadores están encadenados en la misma promesa.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()En paralelo
event_jr
fuente
3
Tenga en cuenta que la nueva respuesta de promesa devuelta una vez que thense llega a un resultado en los métodos successy errordesaparecer. También, para http respuestas de error (por ejemplo, 404) la primera thenen http.then(ok, err).then(ok, err)pasará al errcontrolador pero los siguientes pasará en el okcontrolador. Básicamente http.success().error().success().error()son encadenables, pero las promesas de $ q son bastante diferentes, ya que se trata de la promesa y la secuencia de manejo específicamente (y no del manejo de solicitudes http). Me costó entender esto hasta que lo miré de cerca.
jimmont
1
@jimmont successy errorno son API normales de una promesa, se atornillan al valor de retorno de $ http ().
event_jr
Gracias @event_jr, esto está claro para mí y lo mencioné en los documentos. Lo que no estaba tan claro (para mí) es cómo $ q y $ http resuelven diferentes problemas y devuelven nuevas promesas frente a pasar la misma, como se señala en su respuesta (súper útil).
jimmont
1
¿Qué quiere decir con paralelo, ya que JS es de un solo subproceso? ¿Quiere decir que la orden de ejecución no es determinista?
Derek
2
@Derek el segundo successse ejecutará después de que se haya ejecutado el primero, pero antes de que se resuelva cualquier promesa que se le devuelva, mientras que el segundo thenesperará. Si no está devolviendo promesas, ambos se comportan igual.
Tamlyn
114

Algunos ejemplos de código para una simple solicitud GET. Quizás esto ayude a entender la diferencia. Utilizando 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
});

Usando success/ error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
TheHippo
fuente
55
Gracias, pero la pregunta era más sobre la diferencia en lo que hacen estas funciones o la razón por la que ambas existen si hacen lo mismo. La diferencia en cómo usarlos es comprensible desde el documento.
ejoubaud
39
Personalmente, me gustan los ejemplos de códigos cortos, y es que los publiqué aquí. Los documentos angulares a veces pierden ejemplos cortos y precisos.
TheHippo
2
Es importante resaltar el hecho de que el objeto de respuesta de la primera esencia contiene "datos, estado, encabezado y configuración" de la segunda esencia. Eso significa que los objetos de respuesta tienen un nivel adicional de profundidad.
geoom
¿Hay algún beneficio de pasar los valores de respuesta a las variables data,status,header,configen lugar de simplemente regresar response?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
27

.then () es encadenable y esperará a que se resuelva el anterior .then ().

.success () y .error () se pueden encadenar, pero todos se dispararán a la vez (por lo que no tiene mucho sentido)

.success () y .error () son simplemente buenos para llamadas simples (creadores fáciles):

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

para que no tenga que escribir esto:

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

Pero generalmente manejo todos los errores con .catch ():

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

Si necesita admitir <= IE8, escriba su .catch () y .finally () de esta manera (métodos reservados en IE):

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

Ejemplos de trabajo:

Aquí hay algo que escribí en formato más codey para refrescar mi memoria sobre cómo funciona todo con errores de manejo, etc.

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

nawlbergs
fuente
La única respuesta que muestra cómo funciona el "retorno de otra promesa"
zjk
17

Solo para completar, aquí hay un ejemplo de código que indica las diferencias:

éxito \ error:

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

luego:

$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
fuente
¡genial !, ¿tienes un ejemplo donde la concatenación puede ser útil?
geoom
44
La idea es que el enfoque "entonces" es más útil, ya que puede escribir operaciones asincrónicas más fácilmente una tras otra.
MichaelLo
2

Aviso oficial: el éxito y el error han quedado en desuso, utilice el método estándar y luego en su lugar.

Aviso de desaprobación: los métodos de promesa heredados $ http exitosos y erróneos han quedado desaprobados. Utilice el método estándar de entonces en su lugar. Si $ httpProvider.useLegacyPromiseExtensions se establece en falso, estos métodos arrojarán un error $ http / legacy.

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

captura de pantalla: ver la captura de pantalla

MagicBoy
fuente