Обработка jQuery.ajax продолжает ответы: «успех:» против «.done»?


309

Я работаю с jQuery и AJAX уже несколько недель, и я увидел два разных способа «продолжить» сценарий после вызова: success:и .done.

Из краткого обзора документации jQuery мы получаем:

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

success: (опция .ajax ()): функция, вызываемая в случае успешного выполнения запроса.

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

Ответы:


469

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

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

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

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

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

Хорошая вещь doneв том, что возвращаемое значение $.ajaxтеперь является отложенным обещанием, которое может быть привязано к любому другому месту в вашем приложении. Допустим, вы хотите сделать этот вызов 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определение (обязательно верните обещание или хотя бы 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точно таким же образом.


2
Интересно, как определяются взаимодействия success:/ .done(), если вообще. Например, как success:это реализовано в первые .done()дни?

6
Ты имеешь в виду, если у вас есть и то, success:и другое .doneпо вызову ajax? Хороший вопрос. Поскольку все другие обратные вызовы вызываются в том порядке, в котором они связаны, я думаю, что да, successпросто вызывается первым.
glortho

1
Очень хороший пост! Кстати, в обратном вызове канала не следует ли вызывать функцию канала с параметром jqXHR для проверки ответа о состоянии? Пример: .pipe (функция (data, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder

@Eder Сценарий, к которому я обращаюсь с использованием этого сценария, - это pipeодин из тех случаев, когда сам запрос выполняется успешно, но сценарий на сервере не возвращает то, что вы искали. Возможно, вы не захотите выбрасывать фактические 404 или 500 или что-то еще на стороне сервера, потому что вы хотите существенно различать ответы http и ответы приложения. Задание кода ответа в JSON и последующее использование pipeэтого способа позволяет обрабатывать различные виды ошибок с большим количеством нюансов.
glortho

Еще одним важным преимуществом использования обещаний является то, что ваш код становится намного более читабельным, и вы избегаете «ада обратного вызова». Это особенно верно, когда у вас есть несколько обратных вызовов, которые вы хотите запускать каждый после завершения предыдущего. С обещаниями это будет выглядеть как myPromiseCall.then (..). Then (..) вместо вложенной сложной структуры обратных вызовов, используемой с параметром успеха.
BornToCode

5

Если вам нужен async: falseAjax, вы должны использовать successвместо .done. Остальное тебе лучше использовать .done. Это с официального сайта jQuery :

Начиная с jQuery 1.8, использование async: false с jqXHR ($ .Deferred) устарело; Вы должны использовать параметры обратного вызова success / error / complete вместо соответствующих методов объекта jqXHR, таких как jqXHR.done () .


Кто упомянул async:false?
Лиам

$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
Амир Хоссейн Маниан

0

Из документации JQuery

Объекты jqXHR, возвращаемые начиная с $.ajax()jQuery 1.5, реализуют интерфейс Promise, предоставляя им все свойства, методы и поведение Promise (см. Отложенный объект для получения дополнительной информации). Эти методы принимают один или несколько аргументов функции, которые вызываются при завершении $.ajax()запроса. Это позволяет назначать несколько обратных вызовов для одного запроса и даже назначать обратные вызовы после того, как запрос может быть завершен. (Если запрос уже выполнен, обратный вызов запускается немедленно.) Доступные методы Promise объекта jqXHR включают в себя:

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

Альтернативная конструкция для опции обратного вызова success, обратитесь к deferred.done()подробностям реализации.

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

Альтернативная конструкция для опции обратного вызова с ошибкой, .fail()метод заменяет устаревший метод .error (). Обратитесь к deferred.fail () для деталей реализации.

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

(добавлено в jQuery 1.6) .always()Метод, альтернативный завершенному варианту обратного вызова, метод заменяет устаревший .complete()метод.

В ответ на успешный запрос аргументы функции совпадают с аргументами .done(): data, textStatus и объекта jqXHR. Для неудачных запросов аргументы такие же, как у .fail()объекта jqXHR, textStatus и errorThrown. Обратитесь к deferred.always()подробностям реализации.

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

Включает в себя функциональность .done()и .fail()методов, что позволяет (по состоянию на JQuery 1.8) лежащий в основе Promise манипулировать. Обратитесь к отложенному .then()для деталей реализации.

Deprecation Примечание:jqXHR.success() , jqXHR.error()и jqXHR.complete()обратные вызовы удаляются от JQuery 3.0. Вы можете использовать jqXHR.done(), jqXHR.fail()и jqXHR.always()вместо этого.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.