jQuery.Deferred
Пятница, 19 октября 2012

А помните все те велосипеды, которые приходилось писать для обработки множества асинхронных вызовов? Скажем, у нас есть 10 функций или ajax-запросов. Нужно вызвать их все, подождать пока они отработают, а потом выполнить какой-то общий код. Знакомо, не правда ли? И вот, я случайно обнаружил, что в jQuery подобные вещи уже давно реализованы и их можно использовать. Называется всё это jQuery.Deferred.

Итак, попробуем написать тестовое приложение. Оно запускает 10 таймеров с различным временем. И когда все таймеры сработают, приложение должно вывести какое-нибудь сообщение.

var doAction = function (i) {
    var d = new $.Deferred();
    setTimeout(function () {
        console.log(i + ' done.');
        d.resolve();
    }, Math.random() * 9000 + 1000);
    return d.promise();
};
$(function () {
    var actions = [];
    for (var i = 0; i < 10; ++i) {
        actions.push(doAction(i));
    }
    $.when.apply(this, actions).then(function () {
        console.log('Everything is ok.');
    });
});

У объекта Deferred довольно много всяческих методов, но нам интересно несколько. Метод promise возвращает специальный объект, с помощью которого можно отслеживать состояние выполняемой задачи, методы resolve и reject завершают задачу успешно и не успешно соответственно.

Получив набор объектов promise, мы можем их комбинировать. В нашем случае с помощью $.when создаем новый deferred-объект, который является объединением всех остальных. Ну и с помощью then вешаем общую функцию, которая сработает самой последней.

Ну и напоследок, $.ajax тоже является deferred объектом, поэтому можно написать:

$.when($.ajax(a), $.ajax(b)).then(function () {});

И получить обработчик, который выполнится после завершения всех запросов. Хотя что я вам тут рассказываю, вы ведь всё это знаете и без меня.

← Ошибки bingbot/msnbotgetElementsByClassName в IE →

Хочется что-то добавить или сказать? Я всегда рад обсудить. Пишите на me@dikmax.name.