Некоторое время назад возникла необходимость кэшировать ответы сервера на клиенте. Сразу оговорюсь, что я знаю про кэш браузеров, но это был не мой случай. Не долго думая я начал дополнять код для загрузки данных, что бы перед отправкой запроса на сервер, проверялось нет ли уже результата с таким запросом.
Для наглядности приведу пример до:
function loadData(url, fn) {
ajax.get(url, function (err, result) {
//тут обрабатываем ответ и возвращаем результат
var data = '...';
fn(null, data);
});
}
и после:
var cache = {};
function loadCacheData(url, fn) {
var cacheData = cache[url];
//проверяем кэш
if (cacheData) {
fn(null, cacheData);
} else {
ajax.get(url, function (err, result) {
//тут обрабатываем ответ и возвращаем результат
var data = '...';
//сохраняем в кэш
cache[url] = data;
fn(null, data);
});
}
Переписав в таком стиле еще несколько функций мне стало скучно, да и функционала у такого способа не особо много, например нельзя сбросить кэш. Немного «погуглив» (может плохо гуглил), я так не нашел библиотеки которая позволяла бы простым движением руки прикрутить кэш к уже существующему коду.
Это положило начало к написанию простой функции обертки которая превращала бы loadData в loadCacheData.
Выглядеть это должно примерно так:
function loadData(url, fn) {
ajax.get(url, function (err, result) {
//тут обрабатываем ответ и возвращаем результат
var data = '...';
fn(null, data);
});
}
var loadCacheData = cache(loadData);
Полученная таким способом функция «loadCacheData» должна сама кэшировать результат, а так же предоставлять функционал по управлению кэша.
Через некоторое время удалось реализовать более менее работающую версию функции «cache». Все исходники доступны на github.
Что позволяет делать эта функция:
1. Сброс кэша.
var loadCacheData = cache(loadData);
loadCacheData.clearCache();
2. Устанавливать время жизни для кэша. По умолчанию устанавливает на 1 год.
var loadCacheData = cache({ expire: 10 * 1000 }, loadData);
3. Установка максимального размера кэша (сколько ответов хранить в кэше). По умолчанию 10.
var loadCacheData = cache({ max: 10 }, loadData);
4. Выбор способа хранения кэш. По умолчанию «app».
app — хранить кэш в памяти.
local — хранить кэш в localStorage и доступен между всеми страницами сайта.
var loadCacheData = cache({ storage: 'local' }, loadData);
При установке «local» опционально можно установить «cacheKey» — имя ключа в localStorage где храниться кэш.
5. Установка собственного хранилища для кэша.
var loadCacheData = cache({ storage: new MyCacheStorage() }, loadData);
В этом случае MyCacheStorage() должен реализовывать три метода:
«get(key, fn);» — метод выбирает результаты из кэша по ключу.
«set(key, val, fn);» — метод устанавливает значение к кэш.
«clear(fn);» — метод сбрасывает кэш.
«fn» — функция обратного вызова, принимающая первым аргументом «ошибку», вторым «результат» (если он есть) выполнения функции.
Использование «cache-js» накладывает одно ограничение, функции, результат которых необходимо «закэшировать», должны подчиняться правилу: «Последний параметр должен быть функцией обратного вызова!».
TODO:
- Сейчас функция «cache» добавляется в глобальную область, планируется вынести в отдельную
- Добавить кэш с использованием sessionStorage
- Глобальные опции, например что бы полностью отключить кэш при разработки
- Поддержка старых браузеров. В данный момент используются методы parse/stringify объекта JSON, getItem/setItem/removeItem объекта localStorage
- !? Порт на nodejs (под вопросом)
Примеры с использованием доступны в репозитории
Автор: zxcabs