Решение проблемы кэширования $.ajax в Safari на iOS 6
Быстрый ответ
$.ajaxSetup({ cache: false }); // Вот решение! Глобально отключаем кэширование.
Установив cache: false
глобально, мы предотвращаем натуральную тенденцию Safari в iOS 6 к кэшированию AJAX-запросов, освобождаясь от требования делать это для каждого отдельного вызова. Таким образом, мы гарантируем, что данные с сервера всегда будут свежими.
Почему Safari на iOS 6 так же упорно кеширует данные?
В Safari на iOS 6 используется WebKit, который зачастую сохраняет результаты POST
-запросов в кэше. Согласно стандартам HTTP, это допускается, если заголовок Cache-Control не предписывает иного. Для предотвращения нежелательного кэширования можно воспользоваться следующими методами:
- Использовать заголовок Cache-Control: no-cache в ответах AJAX.
- Присвоить уникальную метку времени каждому запросу.
- Настроить сервер Apache таким образом, чтобы он добавлял заголовки
Cache-Control
для POST-запросов.
Как же настроить сервер?
Поручим эту задачу Apache
Apache может облегчить вам эту задачу: достаточно внести следующие изменения в файл конфигурации:
<FilesMatch "\.(php|cgi|pl)$">
Header set Cache-Control "no-cache" // Так каждый POST-запрос будет автоматически отмечен как "не подлежащий кэшированию"!
</FilesMatch>
Усильте защиту добавлением дополнительных заголовков
Не будет лишним добавить заголовок, который будет служить дополнительной защитой от кэширования:
Pragma: no-cache // Дополнительная мера, позволяющая надежно предотвратить кэширование
По аналогии с HDR на вашем iPhone, это предоставляет дополнительный уровень защиты от нежелательного кэширования.
Когда статические API отказываются кэшировать
Статические API обязаны всегда устанавливать cacheability
в NoCache. Кэширование их ответов под строгим запретом!
Я — клиентский скрипт. Что я могу сделать?
Трюк с меткой времени
Вы можете добавить метку времени к URL запроса с использованием функции getTime()
в JavaScript:
function noCacheUrl(url) {
return url + (url.includes('?') ? '&' : '?') + 'timestamp=' + new Date().getTime()); // Так URL становится уникальным при каждом запросе
}
Автоматическое добавление метки времени в AJAX-запросы
jQuery.ajaxPrefilter позволяет ненавязчиво вставлять метку времени:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (originalOptions.type.toUpperCase() === "POST") {
options.url = noCacheUrl(originalOptions.url); // Каждый POST-запрос будет содержать уникальную метку времени
}
});
Глобальное управление кэшом с помощью $.ajaxSetup. Действуйте как настоящий профессионал!
Установите управление кэшом для всех AJAX-запросов так, чтобы было ясно, кто здесь главный:
$.ajaxSetup({
beforeSend: function(jqXHR) {
jqXHR.setRequestHeader("Cache-Control", "no-cache"); // Сказали кэшу "нет"
jqXHR.setRequestHeader("Pragma", "no-cache"); // На всякий случай усилили наше отрицание
}
});
Небольшой экскурс: время для иллюстрации!
Сформулируем задачу в других терминах: представим, что Safari на iOS 6 – это библиотекарь (👩🏫), который сортирует книги (📚 = запросы). Когда книга возвращается, библиотекарь расставляет ее на полку "Вот что вы читали на прошлой неделе" или просто "Кэш". Чтобы каждый раз получать "новую книгу", мы снабжаем каждый запрос уникальной "закладкой" (🔖 = метка времени).
Стратегии против кэширования для кофе-брейка
Тук-тук! Привет, нежелательное кэширование.
Очень важно, чтобы все разработчики были в курсе особенностей кэширования в Safari на iOS 6. Они не умеют читать мысли, поэтому лучше заранее подстраховаться от возможных проблем.
Не используете jQuery? Не проблема!
Если вы предпочитаете работать без jQuery, то использование XMLHttpRequest
или других библиотек позволит вам эффективно избегать "ледяных островов" кэширования.
Оптимизируйте свою стратегию управления кэшем
От изменения типов запросов до доработки ответов сервера: убедитесь, что ваша стратегия управления кэшем эффективна и грамотно продумана.
Домашняя работа!
Старайтесь следить за обновлениями в документации jQuery и продолжайте изучение других библиотек. Это позволит вам глубже понять тонкости работы с кэшированием.