Кэширование Ajax-запросов

Дата публикации: 04.12.2013

Последнее обновление: 11.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-запросы обычным образом, пребывая в уверенности, что броузер будет отправлять запросы на сервер только в случае отсутствия данных в кэше.

Кроме того, поддержку этой оптимизации легко реализовать на стороне сервера, потому что все языки программирования позволяют устанавливать заголовки тем или иным способом. Это самый простой способ обеспечить кэширование данных.

Пример

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": "<ul><li>Элемент списка №1</li><li>Элемент списка №2</li><li>Элемент списка №3</li></ul>"
}';

echo $json;

Для проверки ajax кэширования, можно воспользоваться прилоежнием firebug для FireFox или DevelopmentTools в Chrome (изображение ниже).

ajax запросы

Если посмотреть тоже самое в firebug — то увидим что не происходит вообще никаких запросов к серверу.

В случае, если необходимо отменить кэширование, необходимо добавлять к строке запроса случайное значение, или если для ajax запроса используются библиотеки типа JQuery, нужно добавить параметр cache: false, этот параметр включает возможность добавления случайного значения к строке запроса — автоматически.

Сохранение данных локально

Для реализации способа локального хранения данные, можно использовать новшества которые предоставляет HTML5:

  • Offline web applications
  • Web SQL Database
  • IndexedDB

Более детально этот раздел будет рассмотрен в следующих материалах.