Кэширование ответа jquery ajax в javascript/browser

Я хотел бы включить кэширование ответа ajax в javascript/browser.

Из документов jquery.ajax:

По умолчанию запросы всегда выдаются, но браузер может выдавать результаты из своего кэша. Чтобы запретить использование кэшированных результатов, установите для кэша значение false. Чтобы запрос сообщал об ошибке, если ресурс не был изменен с момента последнего запроса, установите для ifModified значение true.

Однако ни один из этих адресов не заставляет кешировать.

Мотивация: хочу поставить $.ajax({...}) вызывает в моих функциях инициализации, некоторые из которых запрашивают тот же URL. Иногда мне нужно вызвать одну из этих функций инициализации, иногда я вызываю несколько.

Итак, я хочу минимизировать запросы к серверу, если этот конкретный URL уже был загружен.

Я мог бы бросить свое собственное решение (с некоторыми трудностями!), Но я хотел бы знать, есть ли стандартный способ сделать это.

5 ответов

Решение

cache:true работает только с запросами GET и HEAD.

Вы можете свернуть свое собственное решение, как вы сказали, с чем-то вроде этого:

var localCache = {
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    exist: function (url) {
        return localCache.data.hasOwnProperty(url) && localCache.data[url] !== null;
    },
    get: function (url) {
        console.log('Getting in cache for url' + url);
        return localCache.data[url];
    },
    set: function (url, cachedData, callback) {
        localCache.remove(url);
        localCache.data[url] = cachedData;
        if ($.isFunction(callback)) callback(cachedData);
    }
};

$(function () {
    var url = '/echo/jsonp/';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
            cache: true,
            beforeSend: function () {
                if (localCache.exist(url)) {
                    doSomething(localCache.get(url));
                    return false;
                }
                return true;
            },
            complete: function (jqXHR, textStatus) {
                localCache.set(url, jqXHR, doSomething);
            }
        });
    });
});

function doSomething(data) {
    console.log(data);
}

Рабочая скрипка здесь

РЕДАКТИРОВАТЬ: поскольку этот пост становится популярным, вот еще лучший ответ для тех, кто хочет управлять тайм-аутом тайм-аута, и вам также не нужно беспокоиться обо всем беспорядке в $.ajax(), так как я использую $.ajaxPrefilter(), Сейчас просто настройка {cache: true} достаточно для правильной обработки кеша:

var localCache = {
    /**
     * timeout for cache in millis
     * @type {number}
     */
    timeout: 30000,
    /** 
     * @type {{_: number, data: {}}}
     **/
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    exist: function (url) {
        return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
    },
    get: function (url) {
        console.log('Getting in cache for url' + url);
        return localCache.data[url].data;
    },
    set: function (url, cachedData, callback) {
        localCache.remove(url);
        localCache.data[url] = {
            _: new Date().getTime(),
            data: cachedData
        };
        if ($.isFunction(callback)) callback(cachedData);
    }
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as we have our own localCache
        options.cache = false;
        options.beforeSend = function () {
            if (localCache.exist(url)) {
                complete(localCache.get(url));
                return false;
            }
            return true;
        };
        options.complete = function (data, textStatus) {
            localCache.set(url, data, complete);
        };
    }
});

$(function () {
    var url = '/echo/jsonp/';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
            cache: true,
            complete: doSomething
        });
    });
});

function doSomething(data) {
    console.log(data);
}

И скрипка здесь ОСТОРОЖНА, не работает с $. Отложено

Вот рабочая, но некорректная реализация, работающая с deferred:

var localCache = {
    /**
     * timeout for cache in millis
     * @type {number}
     */
    timeout: 30000,
    /** 
     * @type {{_: number, data: {}}}
     **/
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    exist: function (url) {
        return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
    },
    get: function (url) {
        console.log('Getting in cache for url' + url);
        return localCache.data[url].data;
    },
    set: function (url, cachedData, callback) {
        localCache.remove(url);
        localCache.data[url] = {
            _: new Date().getTime(),
            data: cachedData
        };
        if ($.isFunction(callback)) callback(cachedData);
    }
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        //Here is our identifier for the cache. Maybe have a better, safer ID (it depends on the object string representation here) ?
        // on $.ajax call we could also set an ID in originalOptions
        var id = originalOptions.url+ JSON.stringify(originalOptions.data);
        options.cache = false;
        options.beforeSend = function () {
            if (!localCache.exist(id)) {
                jqXHR.promise().done(function (data, textStatus) {
                    localCache.set(id, data);
                });
            }
            return true;
        };

    }
});

$.ajaxTransport("+*", function (options, originalOptions, jqXHR, headers, completeCallback) {

    //same here, careful because options.url has already been through jQuery processing
    var id = originalOptions.url+ JSON.stringify(originalOptions.data);

    options.cache = false;

    if (localCache.exist(id)) {
        return {
            send: function (headers, completeCallback) {
                completeCallback(200, "OK", localCache.get(id));
            },
            abort: function () {
                /* abort code, nothing needed here I guess... */
            }
        };
    }
});

$(function () {
    var url = '/echo/jsonp/';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
            cache: true
        }).done(function (data, status, jq) {
            console.debug({
                data: data,
                status: status,
                jqXHR: jq
            });
        });
    });
});

Скрипка ЗДЕСЬ Некоторые проблемы, наш идентификатор кэша зависит от представления объекта JSON json2 lib.

Используйте Console view (F12) или FireBug для просмотра некоторых журналов, созданных кешем.

Я искал кеширование для хранения моего телефонного приложения и нашел ответ @TecHunter, который великолепен, но закончил с помощью localCache,

Я нашел и узнал, что localStorage - это еще одна альтернатива для кэширования данных, возвращаемых вызовом ajax. Итак, я создал одну демонстрацию, используя localStorage который поможет другим, кто может захотеть использовать localStorage вместо localCache для кеширования.

Ajax Call:

$.ajax({
    type: "POST",
    dataType: 'json',
    contentType: "application/json; charset=utf-8",
    url: url,
    data: '{"Id":"' + Id + '"}',
    cache: true, //It must "true" if you want to cache else "false"
    //async: false,
    success: function (data) {
        var resData = JSON.parse(data);
        var Info = resData.Info;
        if (Info) {
            customerName = Info.FirstName;
        }
    },
    error: function (xhr, textStatus, error) {
        alert("Error Happened!");
    }
});

Чтобы сохранить данные в localStorage:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (options.cache) {
    var success = originalOptions.success || $.noop,
        url = originalOptions.url;

    options.cache = false; //remove jQuery cache as we have our own localStorage
    options.beforeSend = function () {
        if (localStorage.getItem(url)) {
            success(localStorage.getItem(url));
            return false;
        }
        return true;
    };
    options.success = function (data, textStatus) {
        var responseData = JSON.stringify(data.responseJSON);
        localStorage.setItem(url, responseData);
        if ($.isFunction(success)) success(responseJSON); //call back to original ajax call
    };
}
});

Если вы хотите удалить localStorage, используйте следующую инструкцию, где вы хотите:

localStorage.removeItem("Info");

Надеюсь, это поможет другим!

Все современные браузеры предоставляют вам хранилище apis. Вы можете использовать их (localStorage или sessionStorage) для сохранения ваших данных.

Все, что вам нужно сделать, это после получения ответа сохранить его в хранилище браузера. Затем в следующий раз, когда вы найдете тот же вызов, выполните поиск, если ответ уже сохранен. Если да, верните ответ оттуда; если не сделать свежий звонок.

Плагин Smartjax также делает подобные вещи; но так как ваше требование - просто сохранить ответ на вызов, вы можете написать свой код в вашей функции успеха jQuery ajax, чтобы сохранить ответ. А перед звонком просто проверьте, сохранен ли ответ.

Если я понял ваш вопрос, вот решение:

    $.ajaxSetup({ cache: true});

и для конкретных звонков

 $.ajax({
        url: ...,
        type: "GET",
        cache: false,           
        ...
    });

Если вы хотите противоположное (кеширование для определенных вызовов), вы можете установить false в начале и true для определенных вызовов.

Старый вопрос, но мое решение немного другое.

Я писал одностраничное веб-приложение, которое постоянно выполняло вызовы ajax, запускаемые пользователем, и чтобы сделать его еще более сложным, требовались библиотеки, которые использовали методы, отличные от jquery (например, dojo, native xhr и т. Д.). Я написал плагин для одной из моих собственных библиотек, чтобы кэшировать запросы ajax настолько эффективно, насколько это возможно, так, чтобы это работало во всех основных браузерах, независимо от того, какие библиотеки использовались для выполнения вызова ajax.

Решение использует jSQL (написанное мной - постоянная реализация SQL на стороне клиента, написанная на javascript, которая использует indexeddb и другие методы хранения dom), и поставляется в комплекте с другой библиотекой под названием XHRCreep (написанной мной), которая является полной перезаписью нативный объект XHR.

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

Есть два варианта:

jSQL.xhrCache.max_time = 60;

Установите максимальный возраст в минутах. любые кэшированные ответы, которые старше этого, повторно запрашиваются. По умолчанию 1 час.

jSQL.xhrCache.logging = true;

Когда установлено значение true, ложные вызовы XHR будут отображаться в консоли для отладки.

Вы можете очистить кеш на любой странице через

jSQL.tables = {}; jSQL.persist();
        function getDatas() {
            let cacheKey = 'memories';

            if (cacheKey in localStorage) {
                let datas = JSON.parse(localStorage.getItem(cacheKey));

                // if expired
                if (datas['expires'] < Date.now()) {
                    localStorage.removeItem(cacheKey);

                    getDatas()
                } else {
                    setDatas(datas);
                }
            } else {
                $.ajax({
                    "dataType": "json",
                    "success": function(datas, textStatus, jqXHR) {
                        let today = new Date();

                        datas['expires'] = today.setDate(today.getDate() + 7) // expires in next 7 days

                        setDatas(datas);

                        localStorage.setItem(cacheKey, JSON.stringify(datas));
                    },
                    "url": "http://localhost/phunsanit/snippets/PHP/json.json_encode.php",
                });
            }
        }

        function setDatas(datas) {
            // display json as text
            $('#datasA').text(JSON.stringify(datas));

            // your code here
           ....

        }

        // call
        getDatas();

введите описание ссылки здесь

Другие вопросы по тегам