जावास्क्रिप्ट / ब्राउज़र में एक jquery ajax प्रतिक्रिया का कैशिंग


96

मैं जावास्क्रिप्ट / ब्राउज़र में अजाक्स प्रतिक्रिया के कैशिंग को सक्षम करना चाहूंगा।

से jquery.ajax डॉक्स :

डिफ़ॉल्ट रूप से, अनुरोध हमेशा जारी किए जाते हैं, लेकिन ब्राउज़र अपने कैश से परिणाम निकाल सकता है। कैश्ड परिणामों के उपयोग को अस्वीकार करने के लिए, कैश को गलत पर सेट करें। यदि अंतिम अनुरोध के बाद संपत्ति को संशोधित नहीं किया गया है, तो विफलता की रिपोर्ट करने का अनुरोध करने के लिए, अगर यह सही है।

हालांकि, इनमें से कोई भी पता कैशिंग के लिए मजबूर नहीं करता है।

प्रेरणा: मैं $.ajax({...})अपने आरंभिक कार्यों में कॉल करना चाहता हूं, जिनमें से कुछ समान यूआरएल का अनुरोध करते हैं। कभी-कभी मुझे इन प्रारंभिक कार्यों में से एक को कॉल करने की आवश्यकता होती है, कभी-कभी मैं कई कॉल करता हूं।

इसलिए, मैं सर्वर से अनुरोधों को कम करना चाहता हूं यदि उस विशेष यूआरएल को पहले ही लोड किया गया है।

मैं अपने स्वयं के समाधान को रोल कर सकता था (कुछ कठिनाई के साथ!), लेकिन मैं यह जानना चाहूंगा कि क्या ऐसा करने का कोई मानक तरीका है।


मैंने यह नहीं सोचा होगा कि आपके द्वारा पहले से लोड किए गए URL को ट्रैक करने और उस सूची के विरुद्ध परिणाम संग्रहीत करने में कठिनाई होगी। फिर, AJAX कॉल करने से पहले आप अपने URL की जाँच कर सकते हैं। वोइला - आपके पास अपना मूल कैश है।

आप कैश-नियंत्रण जोड़ सकते हैं और सर्वर पर आपकी प्रतिक्रिया के लिए हेडर को समाप्त कर सकते हैं, इसलिए आपके सर्वर को केवल उस मान में कॉन्फ़िगर किए गए समय समाप्त होने के बाद कॉल किया जाना चाहिए
hereandnow78

जवाबों:


141

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);
}

और यहाँ बेफ़िक्री CAREFUL, $ के साथ काम नहीं कर रहा है

यहाँ एक कार्यशील लेकिन त्रुटिपूर्ण कार्यान्वयन है जो आस्थगित के साथ काम कर रहा है:

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
            });
        });
    });
});

यहाँ कुछ समस्याएँ, हमारी कैश आईडी json2 lib JSON ऑब्जेक्ट प्रतिनिधित्व पर निर्भर है।

कैश द्वारा उत्पन्न कुछ लॉग देखने के लिए कंसोल दृश्य (F12) या FireBug का उपयोग करें।


वहाँ एक कारण आप localCache.setसमारोह पर एक कॉलबैक है ? बस doSomehing(jqXHR)कैश सेट करने के बाद क्यों नहीं ?
कैममिल

मैं इसे इस तरह से पसंद करता हूं, इसलिए मुझे ऐसा कुछ करने की ज़रूरत नहीं है, doSomething(localCache.set(url,jqXHR));लेकिन यह सिर्फ व्यक्तिगत पसंद है
TecHunter

2
एक वादा के रूप में $ .ajax का उपयोग करने के लिए इसे बेहतर बनाने के लिए कोई सुझाव? पहले से झूठे वापस आने से अनुरोध रद्द कर दिया जाता है (जैसा कि यह होना चाहिए) तो मौजूदा $ .ajax (...) किया गया। (फ़ंक्शन (प्रतिक्रिया) {...})। विफल (...) अब काम करना बंद कर दें क्योंकि विफल होने के बजाय इसे लागू किया जाता है। की तुलना में ... और मैं नहीं बल्कि उन सभी को फिर से लिखना होगा :(
franck102

2
@TecHunter इसके लिए बहुत बहुत धन्यवाद। तीन और मामूली सुधार किए जा सकते थे। सबसे पहले, यदि एक ही समय में एक ही संसाधन से कई अनुरोध किए जाते हैं तो वे सभी कैश को याद करेंगे। इसे ठीक करने के लिए आप पहले अनुरोध के साथ लंबित एक निश्चित "आईडी" के लिए कैश सेट करना चाहते हैं और बाद में आने वाले अनुरोधों के लिए परिणाम भेज सकते हैं जब तक कि पहले वापस नहीं आता। दूसरा, आप एक अनुरोध के त्रुटि परिणाम को कैश करना चाह सकते हैं ताकि एक ही संसाधन के सभी अनुरोधों को एक ही परिणाम प्राप्त हो।
mjhm

2
@TecHunter - अच्छा समाधान, मैंने एक महत्वपूर्ण बदलाव के साथ इस समाधान का उपयोग किया। यदि कैश्ड ऑब्जेक्ट को अन्य कार्यों में संशोधित किया जा रहा है, तो यह समस्या पैदा करेगा, इसलिए कैश्ड ऑब्जेक्ट को सेट करने और प्राप्त करने के दौरान, मैं उस ऑब्जेक्ट की प्रतिलिपि वापस कर रहा हूं, जो नीचे दिखाया गया है: localCache.data[url] = { _: new Date().getTime(), data: _.cloneDeep(cachedData, true) }; _.cloneDeep(localCache.data[url].data, true)
भारत पाटिल

12

मैं अपने फोनगैप ऐप स्टोरेज के लिए कैशिंग की तलाश कर रहा था और मुझे @TecHunter का उत्तर मिला जो बहुत अच्छा है लेकिन उपयोग किया जाता है localCache

मैंने पाया और पता चला कि लोकलस्टोरेज एक अन्य विकल्प है जो डेटा को अजाक्स कॉल द्वारा लौटाया जाता है। इसलिए, मैंने एक डेमो बनाया, localStorageजो दूसरों की मदद करेगा जो कैशिंग के localStorageबजाय उपयोग करना चाहते हैं localCache

अजाक्स कॉल:

$.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!");
    }
});

स्थानीयस्टोरेज में डेटा स्टोर करने के लिए:

$.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.removeItem("Info");

आशा है कि यह दूसरों की मदद करता है!


हाय, में localStorage.removeItem("Info");, "info"यह यूआरएल के बारे में है?
२६

@vsogrimen लोकलस्टोरेज infoमें डेटा को स्टोर करने के लिए ऑब्जेक्ट है।
इमयंकमोडी

1
मिलता रहा responseJSON is not defined। इसे ठीक करने का कोई उपाय? (मेरा डेटाटाइप html है)
निकिता '

@CreativeMind, reponseJOSN निकालें, और "var responseData = JSON.stringify (डेटा)" का उपयोग करें; इसके बजाय, सफलता के साथ ऐसा ही करें (डेटा)
यूनिकको

मैं स्थानीय अनुरोध पसंद करता हूं क्योंकि मुझे कई अनुरोधों में कैश की आवश्यकता थी।
कीतेलडोग

9

सभी आधुनिक ब्राउज़र आपको स्टोरेज एपिस प्रदान करते हैं। अपने डेटा को बचाने के लिए आप उन्हें (लोकलस्टोरेज या सेशनस्टोरेज) इस्तेमाल कर सकते हैं।

आपको बस इतना करना है कि प्रतिक्रिया स्टोर करने के बाद इसे ब्राउजर स्टोरेज में जमा कर दें। फिर अगली बार जब आप एक ही कॉल पाते हैं, तो खोजें कि प्रतिक्रिया पहले से ही बच गई है या नहीं। यदि हाँ, तो वहां से प्रतिक्रिया लौटाएं; यदि कोई नया कॉल नहीं किया जाता है।

स्मार्टजैक्स प्लगइन भी इसी तरह की चीजें करता है; लेकिन जैसे-जैसे आपकी आवश्यकता सिर्फ कॉल रिस्पॉन्स को बचा रही है, आप प्रतिक्रिया को बचाने के लिए अपने कोड को अपने jQuery ajax सफलता फ़ंक्शन के अंदर लिख सकते हैं। और कॉल करने से पहले यह देख लें कि रिस्पॉन्स पहले से ही सेव है या नहीं।


IndexedDB में मेरे पास प्रतिक्रियाएं हैं, क्या IndexedDB की जांच करने का कोई तरीका है? इसके अलावा, अगर मैं सत्र भंडारण का उपयोग करता हूं, तो यह देखने का एक तरीका है कि क्या प्रतिक्रिया मौजूद है या jQuery का उपयोग नहीं कर रहा है। मैं jQuery के अलावा किसी भी लाइब्रेरी को शामिल नहीं कर सकता। धन्यवाद,
अभिषेक अग्रवाल

7

अगर मैं आपके सवाल को समझ गया, तो इसका समाधान यहां है:

    $.ajaxSetup({ cache: true});

और विशिष्ट कॉल के लिए

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

यदि आप विपरीत (विशिष्ट कॉल के लिए कैश) चाहते हैं, तो आप शुरुआत में गलत और विशिष्ट कॉल के लिए सही सेट कर सकते हैं।


2
यह ठीक विपरीत है
TecHunter

यह मेरे लिए काम करता है, धन्यवाद! यह अजीब बात है कि मेरे पृष्ठ पर डिफ़ॉल्ट रूप से कैशिंग सक्षम नहीं था ..
तैमूर नुरलीग्यानोव

2

पुराना सवाल है, लेकिन मेरा समाधान थोड़ा अलग है।

मैं एक एकल पेज वेब ऐप लिख रहा था जो लगातार उपयोगकर्ता द्वारा ट्रिगर किए गए अजाक्स कॉल कर रहा था, और इसे और भी कठिन बनाने के लिए आवश्यक पुस्तकालयों का उपयोग किया गया था जिसमें jquery (जैसे डोज़ो, देशी xhr, आदि) के अलावा अन्य तरीकों का इस्तेमाल किया गया था। मैंने अपने स्वयं के पुस्तकालयों के लिए ajax अनुरोधों को कुशलतापूर्वक कैश करने के लिए अपने स्वयं के पुस्तकालयों के लिए एक प्लगइन लिखा है जो सभी प्रमुख ब्राउज़रों में काम करेगा, जिसकी परवाह किए बिना पुस्तकालयों को अजाक्स कॉल करने के लिए उपयोग किया जा रहा था।

समाधान jSQL का उपयोग करता है (मेरे द्वारा लिखा गया - एक क्लाइंट-साइड लगातार SQL कार्यान्वयन जावास्क्रिप्ट में लिखा गया है जो इंडेक्सडब और अन्य डोम भंडारण विधियों का उपयोग करता है), और XHRCreep नामक एक अन्य पुस्तकालय के साथ बंडल किया गया है (मेरे द्वारा लिखित) जो कि एक पूर्ण री-राइट है देशी XHR वस्तु।

आपको जो भी करने की आवश्यकता है उसे लागू करने के लिए अपने पेज में प्लगइन को शामिल करें, जो यहाँ है

दो विकल्प हैं:

jSQL.xhrCache.max_time = 60;

अधिकतम आयु मिनटों में निर्धारित करें। कोई भी कैश की गई प्रतिक्रियाएँ जो इससे अधिक पुरानी हैं, पुनः अनुरोध की जाती हैं। डिफ़ॉल्ट 1 घंटे है।

jSQL.xhrCache.logging = true;

जब सही पर सेट किया जाता है, तो मॉक एक्सएचआर कॉल डिबगिंग के लिए कंसोल में दिखाई जाएगी।

आप किसी भी पेज पर कैशे को क्लियर कर सकते हैं

jSQL.tables = {}; jSQL.persist();

मुझे आपका प्लगइन github और आधिकारिक वेबसाइट में नहीं मिल रहा है। कृपया अपने उत्तर को अपडेट करें मुझे आपके प्लगइन की आवश्यकता है :) मैं github में आपका अनुयायी हूं। अच्छी नौकरी;) @ ओसम-रेजर
एलिकन काबलन

-1
        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();

यहाँ लिंक विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.