в jQuery deferreds и обещаний.тогда() и сделал()



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



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



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

601   8  

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() завершает цепочку обещаний, убедившись, что ничто другое не может присоединить дальнейшие шаги. Это означает, что реализация обещания jQuery может вызвать любое необработанное исключение, так как никто не может обработать его с помощью .fail().

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

Comments

    Ничего не найдено.