Обработка jQuery.ajax продолжается: "success:" vs ".done"?

Я работаю с jQuery и AJAX в течение нескольких недель, и я видел два разных способа "продолжить" script после вызова: success: и .done.

В резюме из документации jQuery мы получаем:

.done(): Описание: Добавить обработчики, вызываемые при разрешении объекта Отложенные.

success: (.ajax() option): функция, которая будет вызываться, если запрос будет успешным.

Итак, оба делают что-то после завершения/разрешения вызова AJAX. Могу ли я использовать одно или другое случайно? В чем разница и когда один используется вместо другого?

Ответ 1

success было традиционным именем обратного вызова успеха в jQuery, определенного как опция в вызове ajax. Однако, поскольку реализация $.Deferreds и более сложные обратные вызовы, done является предпочтительным способом реализации успешных обратных вызовов, поскольку его можно вызвать на любом deferred.

Например, успех:

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

Например, сделано:

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

Самое приятное в done заключается в том, что возвращаемое значение $.ajax теперь является отсроченным обещанием, которое может быть привязано к другому месту в вашем приложении. Итак, скажем, вы хотите сделать этот аякс-звонок из нескольких разных мест. Вместо того, чтобы передавать свою функцию успеха в качестве функции функции, которая делает этот вызов ajax, вы можете просто вернуть функцию $.ajax и привязать свои обратные вызовы с помощью done, fail, then или что-то еще. Обратите внимание, что always - это обратный вызов, который будет запускаться, будет ли запрос успешным или неудачным. done будет срабатывать только при успешном завершении.

Например:

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

Важным преимуществом этого с точки зрения ремонтопригодности является то, что вы завернули свой механизм ajax в специфичную для приложения функцию. Если вы решите, что вам нужен ваш вызов $.ajax для работы по-разному в будущем или вы используете другой метод ajax или вы удаляетесь от jQuery, вам нужно изменить определение xhr_get (обязательно верните обещание или по крайней мере, a done, в случае вышеприведенного примера). Все остальные ссылки в приложении могут оставаться прежними.

С $.Deferred есть еще много (гораздо более крутых) вещей, одним из которых является использование pipe, чтобы вызвать сбой при ошибке, сообщаемой сервером, даже если сам запрос $.ajax, Например:

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

Подробнее о $.Deferred здесь: http://api.jquery.com/category/deferred-object/

ПРИМЕЧАНИЕ. Как и в jQuery 1.8, pipe устарел в пользу использования then точно таким же образом.