jQuery.ajax обробляє подальші відповіді: "успіх:" проти ".done"?


309

Я працюю з jQuery та AJAX вже кілька тижнів, і я побачив два різні способи "продовжити" сценарій після того, як був здійснений дзвінок: success:і .done.

З конспекту документації jQuery ми отримуємо:

.done (): Опис: Додайте обробники для виклику, коли вирішено об’єкт Відкладено.

успіх: (.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на дзвінок в аякс? Хороше питання. Оскільки всі інші зворотні виклики викликаються в порядку, який вони пов'язані, я думаю, що так, successтільки що викликається спочатку.
глорто

1
Дуже приємний пост! Btw, у зворотному звороті труби, чи не слід вам викликати функцію труби за допомогою параметра jqXHR, щоб перевірити відповідь стану? Наприклад: .pipe (функція (data, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Едер

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

Ще одна важлива перевага використання обіцянок полягає в тому, що ваш код стає набагато більш читабельним, і ви уникаєте "пекло зворотного дзвінка". Це істинно вірно, коли у вас є кілька зворотних зворотних дзвінків, які потрібно запустити кожен після завершення попереднього. З обіцянками це виглядатиме як myPromiseCall.then (..). Тоді (..) замість вкладеної складної структури зворотних викликів, що використовується з опцією успіху.
BornToCode

5

Якщо вам потрібно async: falseв аяксі, вам слід використовувати successзамість цього .done. Ще краще вам скористатися .done. Це з офіційного сайту jQuery :

Станом на jQuery 1.8 використання async: false з jqXHR ($ .Deferred) застаріле; ви повинні використовувати параметри зворотного зв'язку успіху / помилки / повного виклику замість відповідних методів об’єкта jqXHR, таких як jqXHR.done () .


Хто згадує async:false?
Ліам

$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian

0

З документації JQuery

Об'єкти jqXHR, повернені $.ajax()станом на jQuery 1.5, реалізують інтерфейс Promise, надаючи їм усі властивості, методи та поведінку обіцянки ( для отримання додаткової інформації див. Відкладений об’єкт ). Ці методи приймають один або кілька аргументів функції, які викликаються, коли $.ajax()запит припиняється. Це дозволяє призначити кілька зворотних дзвінків за одним запитом і навіть призначити зворотні дзвінки після завершення запиту. (Якщо запит вже завершений, зворотний виклик запускається негайно.) Доступні методи обіцянки об’єкта jqXHR включають:

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

Альтернативна конструкція до варіанту зворотного виклику успіху, див 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) маніпулювати основним Обіцянням. Див відклали .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.