Кэширование Ajax-запросов
Дата публикации: 04.12.2013
Самый быстрый Ajax-запрос — тот, который не выполняется. Существует два основных способа предотвратить выполнение ненужных запросов:
- На стороне сервера установить HTTP-заголовки так, чтобы обеспечить сохранение ответа в кэше броузера.
- На стороне клиента сохранять полученные данные локально, чтобы потом не пришлось запрашивать их повторно.
Первый прием является наиболее простым в использовании и сопровождении, тогда как второй обеспечивает более точное управление.
Установка HTTP-заголовков
Если необходимо, чтобы броузер кэшировал Ajax-ответы, запросы должны выполняться методом GET. Но простого использования GET-запросов недостаточно; необходимо также, чтобы в ответе присутствовали нужные HTTP-заголовки. Заголовок Expires сообщает броузеру, как долго должен храниться ответ в кэше. Его значением является дата, по истечении которой любые запросы к этому URL-адресу будут направляться
не в кэш, а на сервер. Ниже показано, как выглядит заголовок Expires:
Expires: Mon, 28 Jul 2014 23:30:00 GMT
Данный заголовок Expires сообщает броузеру, что этот ответ должен храниться в кэше до июля 2014 года. Такие заголовки Expires в далеком будущем удобно использовать для передачи содержимого, которое никогда не изменится, например изображений или статических данных. Дата в заголовке Expires является датой GMT. На языке РНР такой заголовок можно установить следующим способом:
$lifetime = 7 * 24 * 60 * 60; / / 7 дней, в секундах.
header('Expires: ' . gmdate(’D, d М Y H:i:s', time() + $lifetime) . ' GMT');
Этот заголовок сообщает броузеру, что он должен хранить данные в кэше 7 дней. Чтобы установить значение заголовка Expires в далеком будущем, нужно указать в переменной $lifetime более длительный интервал. Следующий пример устанавливает заголовок Expires, сообщающий броузеру, что он должен хранить данные 10 лет:
$lifetime = 10 * 365 * 24 * 60 * 60; // 10 лет, в секундах.
header('Expires: ' . gmdate(’D, d М Y H:i:s', time() + $lifetime) . ' GMT');
Использование заголовка Expires является самым простым способом обеспечить сохранение Ajax-ответов в кэше броузера.
При этом не придется вносить какие-либо изменения в программный код клиентского сценария и можно продолжать выполнять Ajax-запросы обычным образом, пребывая в уверенности, что броузер будет отправлять запросы на сервер только в случае отсутствия данных в кэше.
Кроме того, поддержку этой оптимизации легко реализовать на стороне сервера, потому что все языки программирования позволяют устанавливать заголовки тем или иным способом. Это самый простой способ обеспечить кэширование данных.
Пример
В действии http://jsfiddle.net/valsie/9E5G8/5/
html код
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="js/main.js"></script>
<style>
.status {
float: right;
color: red;
}
</style>
</head>
<body>
<div>
<button id="get-list">Получить список элементов</button>
<span>
<label for="cache-id">Запретить кэширование</label>
<input id="cache-id" type="checkbox" name="cache" value="">
</span>
</div>
<span id="status" class="status"></span>
<div id="list-wrap" class="list-wrap"></div>
</body>
</html>
js код
var AJAX_DEMO = (function() {
var controls = {},
handlers = {
insertContent: function (data) {
controls.listWrap.html(data.list);
},
buttonClick: function () {
var cache = true;
if (controls.check.is(':checked')) {
cache = false;
}
$.ajax({
url: 'php/ajax.php',
data: 'flag=get',
type: 'get',
dataType: 'json',
cache: cache,
success: function (serverAnswer, status, xhr) {
if (xhr.status === 200) {
handlers.insertContent(serverAnswer);
if (!xhr.getResponseHeader('Connection')) {
controls.status.html('Данные взяты из кэша');
} else {
controls.status.html('Данные получены с сервера');
}
} else {
alert(xhr.responseText);
}
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
},
getControls = function () {
controls.button = $('#get-list');
controls.listWrap = $('#list-wrap');
controls.status = $('#status');
controls.check = $('#cache-id');
},
addEventList = function () {
controls.button.on('click', handlers.buttonClick);
};
return {
init: function() {
$(document).ready(function () {
getControls();
addEventList();
});
}
};
})();
AJAX_DEMO.init();
php код
$life_time = 7 * 24 * 60 * 60;
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $life_time) . ' GMT');
$json = '{
"list": "
- Элемент списка №1
- Элемент списка №2
- Элемент списка №3
- Элемент списка №4
»
}’;
echo $json;
Для проверки ajax кэширования, можно воспользоваться прилоежнием firebug для FireFox или DevelopmentTools в Chrome (изображение ниже).

Если посмотреть тоже самое в firebug — то увидим что не происходит вообще никаких запросов к серверу.
В случае, если необходимо отменить кэширование, необходимо добавлять к строке запроса случайное значение, или если для ajax запроса используются библиотеки типа JQuery, нужно добавить параметр cache: false, этот параметр включает возможность добавления случайного значения к строке запроса — автоматически.
Сохранение данных локально
Для реализации способа локального хранения данные, можно использовать новшества которые предоставляет HTML5:
- Offline web applications
- Web SQL Database
- IndexedDB
Более детально этот раздел будет рассмотрен в следующих материалах.
