Каковы возможные методы кэширования ответа Ajax в Javascript?

Я реализую менеджер модуля Javascript, который загружает файлы javascript через объект XHR. Проблема этого метода заключается в кэшировании ресурсов:

  • Во-первых, XHR полагается на встроенный механизм кэширования браузера, который в порядке, но его поведение зависит от реализации браузера.
  • Также существует localStorage, и есть basket.js, который использует localStorage для кэширования загруженных сценариев, проблема в ограниченном размере хранилища, которая обычно составляет 5-10 МБ. Кроме того, localStorage является общим местом для многих сценариев, которые также используют его для хранения данных.
  • И есть интерфейс Cache API ServiceWorker, но он доступен только в ServiceWorker runtime, поэтому он сомневается в моих потребностях.

Кто-нибудь знает какой-то умный старый или новый метод кэширования javascript, который он использует в своем проекте, или, может быть, слышал?

Примечание. Пожалуйста, не предлагайте использовать jQuery .ajax, который является интерфейсом к XHR, или любой другой библиотеке, которая реализует интерфейс встроенных функций Javascript.

Изменить. Были некоторые ценные предложения:

  • Используйте библиотеку под названием localForage. Библиотека представляет собой унифицированный API для индексированныхDB, WebSQL и localStorage, который используется в зависимости от браузера.
  • Используйте IndexedDB, который является действительно мощным хранилищем без существенных ограничений пространства. Единственная проблема заключается в том, что только современные браузеры реализуют IndexedDB.

Ответы

Ответ 1

Это специфично для JQUERY....

Ваш аймакс может быть настроен как кешированный.

    $.ajaxSetup({ cache: true});

и если для определенных вызовов вы не хотите делать кешированный ответ, вызовите

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

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

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

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

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

Ответ 2

Другой конкретный ответ JQUERY?

Не уверен, что он отвечает на ваш вопрос, но это может помочь. Он кэширует ajax-вызовы с таймаутом.

В предфильтрации перечислите различные вызовы ajax для PHP, которые вы хотите добавить для кеширования. В этом примере кеш включен с таймаутом 10 минут.

/*----------------------------*/
/* set ajax caching variables */
/*----------------------------*/
$.set_Ajax_Cache_filters = function () {
    var localCache = {
        timeout: 600000, // 10 minutes
        data: {}, //@type {{_: number, 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) {
            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);
        }
    };

    /*----------------------*/
    /* set ajax pre filters */
    /*----------------------*/
    $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
        // list of allowed url to cache
        if (url !== '..............file.php') {
            return false;
        }
        if (options.cache) {
            var complete = originalOptions.complete || $.noop,
                    url = originalOptions.url;

            options.cache = false;//remove jQuery cache using proprietary one
            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);
            };
        }
    });
};

Ответ 3

Так как indexeddb - это метод, используемый для хранения данных на стороне клиента, позволяет индексировать запросы к базе данных.

И это поддерживаемые браузеры http://caniuse.com/#feat=indexeddb

И это единственные проблемы

Firefox (prior to version 37) and Safari do not support IndexedDB inside web workers.
Not supported in Chrome for iOS or other iOS WebViews.

Chrome 36 and below did not support Blob objects as indexedDB values.

Вот еще один аналогичный polyfill, который вы можете попробовать, но в моем (хотя и ограниченном) опыте оба полифайла ошибочны/неполны. У них обоих также есть много открытых вопросов о GitHub о людях, сообщающих о проблемах. И когда я тестировал один из них (я забыл, какой), он был значительно медленнее, чем собственный IndexedDB.

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

Должен ли я использовать WebSQL, который устарел?

Проблема с WebSQL заключается в том, что она никогда не будет поддерживаться в IE или Firefox. Вероятно, вам удастся уйти с помощью WebSQL, если вы ориентируетесь только на мобильные браузеры, по крайней мере до тех пор, пока Firefox OS или Windows Phone не захватят значительную долю на рынке.

Есть ли планы по поддержке IndexedDB в будущем для всех не поддерживаемых браузеров?

Пусть будет ясно. Вы спрашиваете об Apple, поскольку все остальные поддерживают IndexedDB в своем последнем браузере (iOS Chrome использует механизм рендеринга Apple, потому что Apple не позволит им ничего делать).

Apple не поддерживает IndexedDB, они ничего публично ничего не говорили об этом (насколько я могу судить... и я провела довольно много поиска). Что кажется довольно странным. Поэтому, насколько я могу судить, никто не знает, планирует ли Apple поддерживать IndexedDB. Теоретик-заговор во мне думает, может быть, они пытаются саботировать приложения HTML5, чтобы заставить людей писать собственные приложения, но это чисто спекуляция.

В целом, это оставляет нам разработчиков в довольно хреновой ситуации. Не существует хорошего кросс-платформенного решения. Я рекомендую вам жаловаться на Apple. Это то, что я сделал, и я попросил моих пользователей, которые хотят использовать мое приложение на базе IndexedDB для iOS, сделать то же самое. Еще ни слова от Apple.

UPDATE - Indexeddb теперь поддерживается в iOS 8, как указано в WWDC 2014, но, к сожалению, он сильно прервался.

Считайте также, что Subresource Integrity -

Subresource Integrity позволяет браузерам проверять, что файл поставляется без неожиданных манипуляций.

Нет знаний? пока?

Я предлагаю вам пойти с

Решение Subresource, если мобильным телефоном является ваша главная цель

indexeddb, если мобильный телефон не является вашей основной целью и использует общедоступные реализации для мобильных устройств

Если все вышеперечисленное звучит слишком сложно для вас, то

var localCache = {
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    //a cached version exists
    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); //log only!
        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);
    },
    timeout: 600, //in seconds
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as you have your 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 = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true,
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes, or cached version retrived
    function doSomething(data) {
        console.log(data);
    }

Ответ 4

Чтобы сделать это, лучшая техника использует локальный кеш, ajaxPrefilter и ajax cache, комбинация из этих трех создаст вам необходимый кэш, который вы можете легко контролировать Вот пример кода:

var localCache = {
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    //a cached version exists
    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); //log only!
        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);
    },
    timeout: 600, //in seconds
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as you have your 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 = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true,
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes, or cached version retrived
    function doSomething(data) {
        console.log(data);
    }

Наслаждайтесь кодированием

Ответ 5

Попробуйте это, возможно, будет работать

    var cache = {};
var formatTweets(info) {  
    //formats tweets, does whatever you want with the tweet information
};

//event
$('myForm').addEvent('submit',function() {
    var handle = $('handle').value; //davidwalshblog, for example
    var cacheHandle = handle.toLowerCase();
    if(cache[cacheHandle] != "undefined") {
        formatTweets(cache[cacheHandle]);
    }
    else {
        //gitter
        var myTwitterGitter = new TwitterGitter(handle,{
            count: 10,
            onComplete: function(tweets,user) {
                cache[cacheHandle] = tweets;
                formatTweets(tweets);
            }
        }).retrieve();
    }
});