Кеширование данных, и как с ним бороться.
декабря 6, 2007
Мало мальски серьезное приложение обязательно грузит в себя некие внешние данные.
В случае работы на просторах сети эти данные попадают в кеш.
Иногда эта особенность сильно мешает. К примеру мы делаем галерею которая постоянно пополняется. Адреса изображений заносятся в XML файл, который мы и грузим первым делом в нашу галерею. Единожды загрузившись – этот файл надолго попадает в кеш и наша галерея ничего и знать не знает об обновлениях.
Сценарий 2:
Мы пишем клиентскую часть игры для он-лайн казино. Все процессы связанные с логикой игры происходят на жутко засекреченном сервере, наш клиент только отображает красиво все эти процессы. В определенный момент отправляет серверу данные о действиях игрока, в ответ получая XML с состоянием дел: Баланс игрока, комбинацию карт (или символов, если это слот-машина) ну и много всего разного.
Несмотря на то что мы не запрашиваем реально существующий XML, все равно результат заносится в кеш, и по следующему подобному запросу мы получим старые данные. В итоге – игрок выиграл 100000, но не знает, что это случилось.
Самый простой способ это приклеить Math.random() к запросу. Тогда браузер воспримет такой запрос как абсолютно новый и радостно вернет нам нужные данные в самом свежем виде. Но, полагаться на Math.random() всегда я бы не стал.
И я не стал. Как раз когда мне довелось писать кучу игр для казино, возник вопрос о железной защите от кеша. В итоге родился шизофренический метод, который позже я перелопатил в класс с одним единственным статичным методом. Базируется он на самой непостоянной субстанции – времени.
Однако на этом мы успокаиваться не будем. Иногда нам нужно чтобы свежие данные приходили не так часто. Допустим у меня есть сайт-портфолио, состоящий из нескольких html-страниц. На каждой имеется флеш-галерея работ. Если я буду отключать кеш для каждой загрузки – то мой посетитель будет упорно грузить свежие данные при каждом возвращении на страницу. Выход – обновляться скажем только каждый час, или день.
В общем хватит слов. Класс элементарный – и все будет ясно из его кода.
Метод один Cache.disable(key:String, level:Number);
key – это строка, которую нужно приклеить к запросу. Или банальный «?» («&» если в запросе уже есть пары имя=значение), или что-то сокровенное вроде «?nocache=».
level – уровень защиты от кеша. Передаем одну из констант:
Cache.MONTH, Cache.DAY, Cache.HOUR, Cache.MINUTE, Cache.FULL
код класса:
/** * class Cache * @author Mikhail Ivanchuk * @version 0.1 */ class ru.decafe.utils.Cache { public static var MONTH:Number = 1; public static var DAY:Number = 2; public static var HOUR:Number = 3; public static var MINUTE:Number = 4; public static var FULL:Number = 5; public static function disable(key:String, level:Number):String { if (level == undefined) level = Cache.FULL; var browser:Boolean = (_level0._url.substr(0,4) == "http"); // timestamp var timestamp:Date = new Date(); var timestampY:Number = timestamp.getYear(); var timestampMN:Number = timestamp.getMonth(); var timestampD:Number = timestamp.getDate(); var timestampH:Number = timestamp.getHours(); var timestampM:Number = timestamp.getMinutes(); var timestampS:Number = timestamp.getSeconds(); var timestampMS:Number = timestamp.getMilliseconds(); var timestampMT:Number = Date.UTC(timestampY,timestampMN,timestampD,timestampH,timestampM,timestampS,timestampMS); //date string var dateString:String = timestampY.toString(16) +timestampMN.toString(16); if (level <= Cache.MONTH) return (browser?(key+dateString):""); dateString += timestampD.toString(16); if (level <= Cache.DAY) return (browser?(key+dateString):""); dateString += timestampH.toString(16); if (level <= Cache.HOUR) return (browser?(key+dateString):""); dateString += timestampM.toString(16); if (level <= Cache.MINUTE) return (browser?(key+dateString):""); dateString += timestampS.toString(16)+timestampMS.toString(16)+timestampMT.toString(16); // random var addition:String = (Math.floor(Math.random()*1024)).toString(16); return (browser?(key+dateString+addition):""); } }
Popularity: 11% [?]
Entry Filed under: AS2.0,ActionScript

Один комментарий
1. k0t0vich | января 3, 2008 at 16:36
Еще один вариант, который я использую, это брать в качестве ключа время изменения файла, который необходимо подгрузить ( для swf и картинок)
При апдейте файлов на сервер я запускаю php скрипт который формирует xml страничку с названием файла, размером и датой последнего изменения.
Далее я просто использую фы-цию getCacheURL(string) которая возвращает измененную строку.
Преимущества такого подхода: изменяется линк только для измененных файлов.