Заметки за март 2012 года

Кешируем ассинхронные запросы

Когда на одной странице несколько ajax-запросов выполняются с одними и теми же параметрами и допустимо закешировать результат, то можно сделать это так:

var subscribers = {};

function getSubscribers(id) {
    var dfd = $.Deferred(), promise = dfd.promise();
    if (typeof subscribers[id] !== "undefined") {
        subscribers[id].done(function (count) {
            dfd.resolveWith(promise, [count]);
        });
    } else {
        subscribers[id] = promise;
        $.ajax({
            url: "/subscribers",
            type: "get",
            dataType: "text",
            data: {
                id: id
            }
        })
        .done(function (count) {
            dfd.resolveWith(promise, [count]);
        });
    }
    return promise;
}

Функция вернет promise-объект, который будет разрешен, когда будет известно количество подписчиков.

Если во время запроса на сервер потребуется еще раз получить количество подписчиков, то в этом случае новый ajax-запрос не будет создаваться. Мы подписываемся на результат уже запущенного запроса и ожидаем его успешного завершения.

Все последующие вызовы функции будут возвращать закешированный результат.

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

var cacheable = (function () {
    var promises = {};
    return function (opts) {
        var key = $.param({
                url: opts.url || "",
                type: (opts.type || "get").toLowerCase(),
                data: opts.data || {}
            });
        return promises[key] ? promises[key] :
                (promises[key] = $.ajax(opts).promise());
    };
}());

cacheable({
    url: "/subscribers",
    type: "get",
    dataType: "text",
    data: {
        id: id
    }
});
Комментарии к заметке: 3

Скрываем логику проверки ответа асинхронного запроса

С помощью Deferred Object легко скрыть логику проверки ответа асинхронного запроса.

Считаем, что запрос отработан успешно, если с сервера вернулся JSON и поле status в объект установлено в значение ok. Если там оказалось другое значение, то запрос завершился с ошибкой.

Из метода возвращаем не Deferred XHR, а новый экземпляр обычного отложенного объекта, который в дальнейшем будем «реджектить» или «резолвить».

function subscribe(objectId) {
    var dfd = $.Deferred(),
        p = dfd.promise();

    $.ajax({
        url: "/subscribe",
        type: "post",
        data: {
            objectId: objectId
        }
    }).done(function (data) {
        if (data) {
            if (data.status == "ok") {
                dfd.resolveWith(p);
            } else {
                dfd.rejectWith(p, [data.status]);
            }
        } else {
            dfd.rejectWith(p, ["wrong response"]);
        }
    }).fail(function () {
        dfd.rejectWith(p, ["communication error"]);
    });

    return p;
}

Так как логика обработки ответа отделена от логики приложения, то эта часть кода — хороший кандидат на выделение её в общий для всего приложения обработчик.

Оставте свой комментарий

JavaScript фреймворки. Куда катится мир

Уже становится традицией, что в последние выходные февраля в Челябинск проходит слёт профессионалов, чья работа хоть как-то связана с вебом.

В этом году я представил уважаемой публике доклад на тему «JavaScript фреймворки. Куда катится мир». Хотел опубликовать слайды к докладу вместе с видео. Но, похоже, в этом году его не будет.

Итак, слайды с комментариями или в формате PDF.

Оставте свой комментарий