Когда на одной странице несколько 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
}
});
Коментарии к заметке
Позавчера сделал почти то же самое для своих социальных кнопок, очень удобно: https://gist.github.com/2235116
Идеи летают в воздухе — только успевай хватать.
http://maximdenisov.ru/453.html
[…] Аналогичный приём, но без использования Underscore.js я применяю для кеширования асинхронных запросов. […]