в jQuery deferreds и обещаний.тогда() и сделал()
Я читал о jQuery deferreds и обещаниях, и я не вижу разницы между использованием .then() & .done() для успешных вызовов. Я знаю Эрик Hynds отмечает, что .done() и .success() карта с той же функциональностью, но я предполагаю, что так делает .then() поскольку все обратные вызовы вызываются при завершении успешной операции.
может кто-нибудь просветить меня на правильное использование?
большое спасибо
8 ответов:
обратные вызовы, прикрепленные к
done()будет уволен, когда отложенный будет разрешен. Обратные вызовы, прикрепленные кfail()будет уволен, когда отложенный отклоняется.до jQuery 1.8,
then()была просто синтаксический сахар:promise.then( doneCallback, failCallback ) // was equivalent to promise.done( doneCallback ).fail( failCallback )по состоянию на 1.8,
then()псевдонимpipe()и возвращает новое обещание, увидеть здесь подробнее о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---------- обновление:
кстати. Я забыл упомянуть, что если вы возвращаете обещание вместо значения атомарного типа, внешнее обещание будет ждать, пока внутреннее обещание решает:
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()есть только один сбой обратного вызоватак это до вас, что вы должны сделать... вас волнует, если это удастся или если это не удастся?
отложить.сделано()
добавляет обработчики для вызова только когда отложено решается. Вы можете добавить несколько обратных вызовов для вызова.
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);отложить.тогда()
добавляет обработчики для вызова когда отложенный разрешен, отклонен или все еще выполняется.
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 предназначены для реализации обещаний (и jQuery3.0 фактически пытается привести их в спецификацию).
ключевое различие между done / then заключается в том, что
.done()всегда возвращает те же значения Promise / wrapped, с которых он начинался, независимо от того, что вы делаете или что вы возвращаете..then()всегда возвращает новое обещание, и вы отвечаете за контроль то, что это обещание основано на том, что функция, которую вы передали, она вернула.в переводе с jQuery на родной ES2015 обещает,
.done()это похоже на реализацию структуры " tap "вокруг функции в цепочке обещаний, в которой она будет, если цепочка находится в состоянии" resolve", передавать значение функции... но результат этой функции не повлияет на саму цепь.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.
обратите внимание, что я сделал и не надо делать лесозаготовки, нет .затем. Это потому что консоль.функции журнала на самом деле ничего не возвращают. И что произойдет, если вы пройдете .тогда функция, которая ничего не возвращает?
Promise.resolve(5) .then(doneWrap( x => x + 1)) .then(console.log.bind(console)) .then(console.log.bind(console));вот лог:
5
неопределено
что случилось? Когда я использовал .затем и передал ему функцию, которая ничего не возвращала, ее неявный результат был "неопределенным"... который, конечно же, вернул обещание[неопределенное] далее следует метод, который регистрируется неопределенным. Таким образом, первоначальное значение, с которого мы начали, было в основном потеряно.
.then()- это, в сердце, в виде композиции функций: результат каждого шага используется в качестве аргумента для функции на следующем шаге. Вот почему.done лучше всего рассматривать как "кран" - > это на самом деле не часть композиции, просто что-то, что пробирается на значение на определенном шаге и запускает функцию с этим значением, но на самом деле не изменяет композицию в любом случае путь.это довольно фундаментальное различие, и, вероятно, есть веская причина, по которой родные обещания не имеют .сделанный метод реализовали сами. Мы не должны вдаваться в то, почему нет .не метод, потому что это еще сложнее (а именно, .неудача./улов не являются зеркалами .сделанный./затем -> функции .поймайте, что возвращаемые голые значения не" остаются " отклоненными, как те, которые были переданы .тогда они решают!)
then()всегда означает, что он будет вызван в любом случае. Но передача параметров различна в разных версиях jQuery.до jQuery 1.8,
then()равнаdone().fail(). И все функции обратного вызова имеют одинаковые параметры.но по состоянию на jQuery 1.8,
then()возвращает новое обещание, и если она возвращает значение, оно будет передано в следующую функцию обратного вызова.давайте посмотрим следующее пример:
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()функция всегда передает один и тот же отложенный объект следующей функции.но по состоянию на jQuery 1.8, результат должен быть:
result = 3 result = 7 result = NaNПотому что первый
then()функция возвращает новое обещание, и значение 7 (и это единственный параметр, который будет передан)передается следующемуdone(), так чтоdone()пишиresult = 7. Второйthen()принимает 7 в качестве значенияaи занимаетundefinedкак значениеb, так чтоthen()возвращает новое обещание с параметром NaN, а последнееdone()печатает NaN в результате.
есть очень простое ментальное отображение в ответ, которое было немного трудно найти в других ответах:
doneосуществляетtapа в Синяя птица обещает
thenосуществляетthenа в ES6 обещает
.done()завершает цепочку обещаний, убедившись, что ничто другое не может присоединить дальнейшие шаги. Это означает, что реализация обещания jQuery может вызвать любое необработанное исключение, так как никто не может обработать его с помощью.fail().на практике, если вы не планируете присоединять больше шагов к обещанию, вы должны использовать
.done(). Для получения более подробной информации см. почему обещания должны быть выполнены
Comments