jQuery.ajax manejo continuar respuestas: "éxito:" vs ".done"?

309

He estado trabajando con jQuery y AJAX durante algunas semanas y vi dos formas diferentes de 'continuar' el script una vez que se realizó la llamada: success:y .done.

De la sinopsis de la documentación de jQuery obtenemos:

.done (): Descripción: Agregue controladores a los que se llamará cuando se resuelva el objeto diferido.

success: (opción .ajax ()): una función que se llamará si la solicitud se realiza correctamente.

Entonces, ambos hacen algo después de que la llamada AJAX se ha completado / resuelto. ¿Puedo usar uno u otro al azar? ¿Cuál es la diferencia y cuándo se usa uno en lugar del otro?

Claudio
fuente

Respuestas:

469

successha sido el nombre tradicional de la devolución de llamada exitosa en jQuery, definida como una opción en la llamada ajax. Sin embargo, desde la implementación de $.Deferredsdevoluciones de llamada más sofisticadas, donees la forma preferida de implementar devoluciones de llamada exitosas, ya que se puede invocar en cualquiera deferred.

Por ejemplo, el éxito:

$.ajax({
  url: '/',
  success: function(data) {}
});

Por ejemplo, hecho:

$.ajax({url: '/'}).done(function(data) {});

Lo bueno donees que el valor de retorno de $.ajaxahora es una promesa diferida que puede vincularse a cualquier otro lugar de su aplicación. Digamos que desea hacer esta llamada ajax desde diferentes lugares. En lugar de pasar en su función de éxito como una opción para la función que hace que esta llamada AJAX, sólo puede tener la función de retorno $.ajaxa sí mismo y se unen sus devoluciones de llamada con done, fail, then, o lo que sea. Tenga en cuenta que alwayses una devolución de llamada que se ejecutará si la solicitud tiene éxito o falla. donesolo se activará en caso de éxito.

Por ejemplo:

function xhr_get(url) {

  return $.ajax({
    url: url,
    type: 'get',
    dataType: 'json',
    beforeSend: showLoadingImgFn
  })
  .always(function() {
    // remove loading image maybe
  })
  .fail(function() {
    // handle request failures
  });

}

xhr_get('/index').done(function(data) {
  // do stuff with index data
});

xhr_get('/id').done(function(data) {
  // do stuff with id data
});

Un beneficio importante de esto en términos de mantenibilidad es que ha incluido su mecanismo ajax en una función específica de la aplicación. Si decide que necesita su $.ajaxllamada para operar de manera diferente en el futuro, o usa un método ajax diferente, o se aleja de jQuery, solo tiene que cambiar la xhr_getdefinición (asegúrese de devolver una promesa o al menos un donemétodo, en El caso del ejemplo anterior). Todas las demás referencias en la aplicación pueden seguir siendo las mismas.

Hay muchas cosas más (mucho más geniales) con las que puede hacer $.Deferred, una de las cuales es usar pipepara desencadenar una falla en un error informado por el servidor, incluso cuando la $.ajaxsolicitud en sí misma tiene éxito. Por ejemplo:

function xhr_get(url) {

  return $.ajax({
    url: url,
    type: 'get',
    dataType: 'json'
  })
  .pipe(function(data) {
    return data.responseCode != 200 ?
      $.Deferred().reject( data ) :
      data;
  })
  .fail(function(data) {
    if ( data.responseCode )
      console.log( data.responseCode );
  });
}

xhr_get('/index').done(function(data) {
  // will not run if json returned from ajax has responseCode other than 200
});

Lea más sobre $.Deferredaquí: http://api.jquery.com/category/deferred-object/

NOTA : A partir de jQuery 1.8, pipeha quedado en desuso a favor de usarlo thenexactamente de la misma manera.

revs glortho
fuente
2
Me pregunto cómo se definen las interacciones de success:/ .done(), en todo caso. Por ejemplo, ¿ success:solo se implementa como el primero en .done()estos días?
66
¿Quieres decir si tienes ambas success:y .doneen una llamada ajax? Buena pregunta. Como todas las demás devoluciones de llamada se llaman en el orden en que están vinculadas, supongo que sí, successsolo se llama primero.
glortho
1
Muy buena publicación! Por cierto, en la devolución de llamada de la tubería, ¿no debería llamar a la función de tubería con el parámetro jqXHR para verificar la respuesta de estado? Ej: .pipe (function (data, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder
@Eder El escenario que estoy abordando con este uso pipees uno en el que la solicitud en sí tiene éxito pero el script en el servidor no devolvió lo que estaba buscando. Es posible que no desee arrojar un 404 o 500 real o lo que sea en el lado del servidor porque desea distinguir significativamente entre las respuestas http y las respuestas de la aplicación. Establecer un código de respuesta en el JSON y luego usarlo de pipeesta manera le permite manejar diferentes tipos de errores con más matices.
glortho
Otro beneficio importante de usar promesas es que su código se vuelve mucho más legible y evita el 'infierno de devolución de llamada'. Esto es especialmente cierto cuando tiene múltiples devoluciones de llamada que desea ejecutar cada una después de que finalizó la anterior. Con promesas, se vería como myPromiseCall.then (..). Luego (..) en lugar de una estructura complicada anidada de devoluciones de llamada utilizadas con la opción de éxito.
BornToCode
5

Si necesita async: falseen su ajax, debe usar en successlugar de .done. De lo contrario, es mejor usar .done. Esto es del sitio oficial de jQuery :

A partir de jQuery 1.8, el uso de async: false con jqXHR ($ .Deferred) está en desuso; usted debe usar los / error / éxito completas opciones de devolución de llamada en lugar de los métodos correspondientes del objeto jqXHR como jqXHR.done () .

AmirHossein Manian
fuente
Quien menciona async:false?
Liam
$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian
0

De la documentación de JQuery

Los objetos jqXHR devueltos por $.ajax()jQuery 1.5 implementan la interfaz Promise, dándoles todas las propiedades, métodos y comportamiento de una Promesa (consulte Objeto diferido para obtener más información). Estos métodos toman uno o más argumentos de función que se invocan cuando $.ajax()finaliza la solicitud. Esto le permite asignar múltiples devoluciones de llamada en una sola solicitud, e incluso asignar devoluciones de llamada después de que la solicitud se haya completado. (Si la solicitud ya está completa, la devolución de llamada se activa inmediatamente). Los métodos de Promesa disponibles del objeto jqXHR incluyen:

jqXHR.done(function( data, textStatus, jqXHR ) {});

Una construcción alternativa a la opción de devolución de llamada exitosa, consulte los deferred.done()detalles de implementación.

jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});

Una construcción alternativa a la opción de devolución de llamada de error, el .fail()método reemplaza el método .error () en desuso. Consulte deferred.fail () para obtener detalles de implementación.

jqXHR.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) { }); 

(agregado en jQuery 1.6) Una construcción alternativa a la opción de devolución de llamada completa, el .always()método reemplaza el .complete()método en desuso .

En respuesta a una solicitud exitosa, los argumentos de la función son los mismos que los de .done(): data, textStatus y el objeto jqXHR. Para solicitudes fallidas, los argumentos son los mismos que los de .fail(): el objeto jqXHR, textStatus y errorThrown. Consulte deferred.always()para detalles de implementación.

jqXHR.then(function( data, textStatus, jqXHR ) {}, function( jqXHR, textStatus, errorThrown ) {});

Incorpora la funcionalidad de los métodos .done()y .fail(), lo que permite (a partir de jQuery 1.8) manipular la promesa subyacente. Consulte diferido .then()para obtener detalles de implementación.

Deprecation Aviso: El jqXHR.success(), jqXHR.error()y jqXHR.complete()devoluciones de llamada se retiran a partir de jQuery 3.0. Se puede utilizar jqXHR.done(), jqXHR.fail()y jqXHR.always()en su lugar.

Sasmit
fuente