jQuery откладывает и обещает – .then () vs .done ()

Я читал о jQuery отложенных и обещаниях, и я не вижу разницы между использованием .then() & .done() для успешных обратных вызовов. Я знаю, что Эрик Хиндс упоминает, что .done() и .success() сопоставляются с той же функциональностью, но я предполагаю, что так .then() поскольку все обратные вызовы вызваны при завершении успешной операции.

Может ли кто-нибудь просветить меня до правильного использования?

Большое спасибо

Обратные вызовы, прикрепленные к done() будут запущены, когда отложен запрос. Обратные вызовы, связанные с fail() будут уволены, когда отложенные отклоняются.

До jQuery 1.8, then() был просто синтаксическим сахаром:

 promise.then( doneCallback, failCallback ) // was equivalent to promise.done( doneCallback ).fail( failCallback ) 

Начиная с версии 1.8, then() является псевдонимом для pipe() и возвращает новое promise, см. Здесь для получения дополнительной информации о pipe() .

success() и error() доступны только для объекта jqXHR возвращаемого вызовом ajax() . Это простые псевдонимы для done() и fail() соответственно:

 jqXHR.done === jqXHR.success jqXHR.fail === jqXHR.error 

Кроме того, done() не ограничивается одним обратным вызовом и отфильтровывает не-функции (хотя в версии 1.8 есть ошибка со строками, которая должна быть исправлена ​​в 1.8.1):

 // this will add fn1 to 7 to the deferred's internal callback list // (true, 56 and "omg" will be ignored) promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 ); 

То же самое относится к fail() .

Существует также разница в способе обработки результатов обработки (его называемая цепочка, done не цепочка, а then создает цепочки вызовов)

 promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return 123; }).then(function (x){ console.log(x); }).then(function (x){ console.log(x) }) 

Будут записаны следующие результаты:

 abc 123 undefined 

В то время как

 promise.done(function (x) { // Suppose promise returns "abc" console.log(x); return 123; }).done(function (x){ console.log(x); }).done(function (x){ console.log(x) }) 

получит следующее:

 abc abc abc 

———- Обновить:

Btw. Я забыл упомянуть, если вы вернете promise вместо значения атомного типа, внешнее promise будет ждать, пока не будет разрешено внутреннее promise:

 promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return $http.get('/some/data').then(function (result) { console.log(result); // suppose result === "xyz" return result; }); }).then(function (result){ console.log(result); // result === xyz }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then }) 

таким образом становится очень просто составить параллельные или последовательные асинхронные операции, такие как:

 // Parallel http requests promise.then(function (x) { // Suppose promise returns "abc" console.log(x); var promise1 = $http.get('/some/data?value=xyz').then(function (result) { console.log(result); // suppose result === "xyz" return result; }); var promise2 = $http.get('/some/data?value=uvm').then(function (result) { console.log(result); // suppose result === "uvm" return result; }); return promise1.then(function (result1) { return promise2.then(function (result2) { return { result1: result1, result2: result2; } }); }); }).then(function (result){ console.log(result); // result === { result1: 'xyz', result2: 'uvm' } }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then }) 

Вышеупомянутый код выдает два HTTP-запроса параллельно, тем самым делая запросы завершенными раньше, тогда как ниже эти HTTP-запросы выполняются последовательно, что снижает нагрузку на сервер

 // Sequential http requests promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return $http.get('/some/data?value=xyz').then(function (result1) { console.log(result1); // suppose result1 === "xyz" return $http.get('/some/data?value=uvm').then(function (result2) { console.log(result2); // suppose result2 === "uvm" return { result1: result1, result2: result2; }; }); }); }).then(function (result){ console.log(result); // result === { result1: 'xyz', result2: 'uvm' } }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then }) 

.done() имеет только один обратный вызов и это обратный вызов успеха

.then() имеет как успешные, так и отказоустойчивые обратные вызовы

.fail() имеет только один .fail() вызов

так что вам решать, что вы должны делать … вам все равно, удастся ли ему это сделать или если это не удастся?

deferred.done ()

добавляет обработчики, которые будут вызываться только тогда, когда Deferred разрешен . Вы можете добавить несколько обратных вызовов для вызова.

 var url = 'http://jsonplaceholder.typicode.com/posts/1'; $.ajax(url).done(doneCallback); function doneCallback(result) { console.log('Result 1 ' + result); } 

Вы также можете написать выше, как это,

 function ajaxCall() { var url = 'http://jsonplaceholder.typicode.com/posts/1'; return $.ajax(url); } $.when(ajaxCall()).then(doneCallback, failCallback); 

deferred.then ()

добавляет обработчики, которые будут вызываться, когда Deferred разрешен, отклонен или все еще продолжается .

 var url = 'http://jsonplaceholder.typicode.com/posts/1'; $.ajax(url).then(doneCallback, failCallback); function doneCallback(result) { console.log('Result ' + result); } function failCallback(result) { console.log('Result ' + result); } 

На самом деле существует довольно критическое различие, поскольку JQuery’s Deferreds предназначается для реализации обещаний (и jQuery3.0 на самом деле пытается привести их в спецификацию).

Ключевое различие между сделанными /

  • .done() ВСЕГДА возвращает те же самые значения Promise / wrapped, с которых он начинался, независимо от того, что вы делаете или что вы возвращаете.
  • .then() всегда возвращает NEW Promise, и вы отвечаете за контроль над тем, что это promise основано на том, что передала функция, которую вы передали.

Переведенный из jQuery в собственный ES2015 Promises, .done() похож на реализацию структуры «касания» вокруг функции в цепочке Promise, поскольку она будет, если цепочка находится в состоянии «разрешить», передать значение функция … но результат этой функции НЕ будет влиять на цепочку.

 const doneWrap = fn => x => { fn(x); return x }; Promise.resolve(5) .then(doneWrap( x => x + 1)) .then(doneWrap(console.log.bind(console))); $.Deferred().resolve(5) .done(x => x + 1) .done(console.log.bind(console)); 

Они будут регистрировать 5, а не 6.

Обратите внимание, что я использовал done и doneWrap для ведения журнала, а не. Then. Это потому, что функции console.log фактически ничего не возвращают. И что произойдет, если вы пройдете. Then функция, которая ничего не возвращает?

 Promise.resolve(5) .then(doneWrap( x => x + 1)) .then(console.log.bind(console)) .then(console.log.bind(console)); 

Это будет вести журнал:

5

не определено

Что случилось? Когда я использовал .then и передал ему функцию, которая ничего не возвращала, это неявный результат был «undefined» … который, конечно же, возвратил Promise [undefined] в следующий, затем метод, который регистрировался неопределенно. Таким образом, первоначальное значение, с которого мы начали, в основном было потеряно.

.then() – это, по сути, форма функционального состава: результат каждого шага используется в качестве аргумента для функции на следующем шаге. Вот почему лучше всего подумать о «постукивании» -> это не на самом деле часть композиции, просто что-то, что подкрадывается к значению на определенном шаге и запускает функцию при этом значении, но на самом деле не меняет композиции в любом случае.

Это довольно фундаментальное различие, и, вероятно, есть веская причина, по которой собственные обещания не имеют метода .done. Нам не нужно разбираться в том, почему нет метода .fail, потому что это еще сложнее (а именно .fail / .catch НЕ являются зеркалами .done / .then-> функций в .catch, которые возвращают голые значения, не «остаться» отвергнутым, как те, которые были переданы. Затем они решаются!)

then() всегда означает, что он будет вызван в любом случае. Но передача параметров различна в разных версиях jQuery.

До jQuery 1.8, then() равно done().fail() . И все функции обратного вызова имеют одинаковые параметры.

Но с jQuery 1.8, then() возвращает новое promise, и если оно возвращает значение, оно будет передано в следующую функцию обратного вызова.

Давайте посмотрим следующий пример:

 var defer = jQuery.Deferred(); defer.done(function(a, b){ return a + b; }).done(function( result ) { console.log("result = " + result); }).then(function( a, b ) { return a + b; }).done(function( result ) { console.log("result = " + result); }).then(function( a, b ) { return a + b; }).done(function( result ) { console.log("result = " + result); }); defer.resolve( 3, 4 ); 

До jQuery 1.8 ответ должен быть

 result = 3 result = 3 result = 3 

Весь result принимает 3. И then() функция then() всегда передает один и тот же отложенный объект следующей функции.

Но с jQuery 1.8 результат должен быть:

 result = 3 result = 7 result = NaN 

Поскольку первая функция then() возвращает новое promise, а значение 7 (и это единственный параметр, который будет передан) передается следующему done() , поэтому второй результат done() write result = 7 . Второй then() принимает 7 как значение a и принимает undefined значение b , поэтому второй then() возвращает новое promise с параметром NaN, а последнее done() выводит NaN в качестве результата.

В ответе очень простое ментальное отображение, которое было немного сложно найти в других ответах:

  • done реализует tap как в голубых птицах. Обещания

  • then реализует then как в ES6 Promises

.done() завершает цепочку обещаний, убедившись, что ничто другое не может приложить дальнейшие шаги. Это означает, что реализация обещания jQuery может вызывать любое необработанное исключение, поскольку никто не может справиться с ним с помощью .fail() .

На практике, если вы не планируете прилагать больше шагов к обещанию, вы должны использовать .done() . Подробнее см., Почему необходимо выполнить обещания

  • AngularJS: Где использовать обещания?
  • Возrotation обещаний от действий Vuex
  • Angularjs $ q.all
  • Угловой HttpPromise: разница между методами `success` /` error` и аргументами `then`
  • Что произойдет, если я отклоняю / разрешаю несколько раз в цикле Крисковаля?
  • Угловой JS: как привязываться к обещаниям
  • Давайте будем гением компьютера.