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

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

Пример

В действии 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 (изображение ниже).

ajax запросы

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

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

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

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

  • Offline web applications
  • Web SQL Database
  • IndexedDB

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

Показать комментарии