Открыть меню    

Отсроченные объекты jQuery

Отсроченные объекты (deferred objects) - этот термин применяется в jQuery с целью акцентировать внимание на наборе улучшений для функций обратного вызова.

Отсроченные объекты позволяют применять функции обратного вызова везде, а не только лишь при реагировании на события.

jQuery


// Создаем Отсроченный объект
var def = $.Deferred();

def.done(function() {
    displayMessage("функция обратного вызова исполнена");
})

$("button").button().click(function() {
    def.resolve();
})

displayMessage("Готово")


function displayMessage(msg) {
    $("tbody").append("<tr><td>" + msg + "</td></tr>")
}
  • $.Deferred() возвращает отсроченный объект.
  • С помощью метода done регистрируем функцию обратного вызова
  • метод resolve переводит отсроченный объект в состояние "успещно выполнен". При выполнении функции resolve запускается функция, зарегистрированная в методе done.
  • Пока не будет вызван метод resolve Отсроченный объект будет находиться в состоянии "еще не выполнено"

Асинхронный пример

jQuery

$(document).ready(function() {
    var def = $.Deferred();

    def.done(function() {
        showMessage("функция обратного вызова исполнена");
    })

    function longTask() {

        setTimeout(function() {
            var start = $.now();
            var total = 0;
            for (var i = 0; i < 500000000 ; i++) {
                total += i;
            }
            var elapsedTime = (($.now() - start)/1000).toFixed(1)
            showMessage("Задача завершена. Время: " + elapsedTime + " sec")
            def.resolve();
        }, 10);

    }

    $("button").button().click(function() {
        showMessage("Вызов longTask()")
        longTask()
        showMessage("longTask() Возвращена")
    })

    showMessage("Готово")
})

function showMessage(msg) {
    $("body").append(msg + "<br/>")
}

/*
Готово
Вызов longTask()
longTask() Возвращена
Задача завершена. Время: 0.4 sec
функция обратного вызова исполнена
*/

    

В качестве аргумента можно передать функцию, которая произведет инициализацию готового объекта, прямо перед его возвращением из конструктора. Внутри этой функции, deferred-объект будет доступен в переменной this и в первом аргументе (obj).

Используя эту возможность можно создать функцию-оболочку, которая асинхронно выполняет всю работы и после этого выполняется функция обратного вызова.

jQuery

function performLongTask() {
    return $.Deferred(function(def) {
        setTimeout(function() {
            performLongTaskSync();
            def.resolve();
        }, 10)
    })
}

jQuery

        $(document).ready(function() {

            function performLongTaskSync() {
                var start = $.now();

                var total = 0;
                for (var i = 0; i < 500000000 ; i++) {
                    total += i;
                }
                var elapsedTime = (($.now() - start)/1000).toFixed(1)
                displayMessage("Задача завершена. Время: " + elapsedTime + " sec")
                return total;
            }

            function performLongTask() {
                return $.Deferred(function(def) {
                    setTimeout(function() {
                        performLongTaskSync();
                        def.resolve();
                    }, 10)
                })
            }

            $("button").button().click(function() {
                if ($(":checked").length > 0) {
                    // АСИНХР.
                    displayMessage("Вызов performLongTask()")
                    var observer = performLongTask();
                    observer.done(function() {
                        displayMessage("функция обратного вызова исполнена");
                    });
                    displayMessage("Возврат из performLongTask()")
                } else {
                    // СИНХР.
                    displayMessage("Вызов performLongTaskSync()")
                    performLongTaskSync();
                    displayMessage("Возврат из performLongTaskSync()")
                }
            })

            $(":checkbox").button();
            displayMessage("Готово")
        })

        function displayMessage(msg) {
            $("tbody").append("<tr><td>" + msg + "</td></tr>")
        }
/*
СИНХР.:
Готово
Вызов performLongTaskSync()
Задача завершена. Время: 0.4 sec
Возврат из performLongTaskSync()

АСИНХР.:
Готово
Вызов performLongTask()
Возврат из performLongTask()
Задача завершена. Время: 0.4 sec
функция обратного вызова исполнена
*/

Что Чем запускается

  • done() запускается resolve()
  • fail() запускается reject()
  • always() запускается resolve() или reject()

Аргументы в resolve() и reject()

Методам resolve() и reject() можно передавать аргументы. В этом случае передаваемые объекты будут передаваться функциям обратного вызова.

def.resolve("text");
def.reject("text");

def.resolve({
    var: "HAHA"
});

then

Если у вас преусмотрены оба исхода, то их можно использовать в then(). У then 1-й аргумент это функция которая используется, когда отстроченный объект принимается; 2-й параметр - функция, которая вызывается при отклонении.

always

Функция, зарегестрированная в always, выполняется в любом случае.

when

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

$.when(obj1, obj2, obg3).done(fucntion(){
    //......
})
.fail(fucntion(){
    //......
})

Отсроченный объекты и ajax

Объект jqXHR, возвращаемый, например, методом ajax(), реализует интерфейс PROMISE, который предоставляет множество методом, опредеяемых отсроченный объектом (done(), fail(), always(), when()).

Комментарии к статье