[javascript] 자바 스크립트 / 브라우저에서 jquery ajax 응답 캐싱

javascript / browser에서 ajax 응답의 캐싱을 활성화하고 싶습니다.

로부터 jquery.ajax 워드 프로세서 :

기본적으로 요청은 항상 발행되지만 브라우저는 캐시에서 결과를 제공 할 수 있습니다. 캐시 된 결과의 사용을 허용하지 않으려면 cache를 false로 설정하십시오. 마지막 요청 이후 자산이 수정되지 않은 경우 요청이 실패를보고하도록하려면 ifModified를 true로 설정하십시오.

그러나 이러한 주소 중 어느 것도 캐싱을 강제하지 않습니다.

동기 부여 :$.ajax({...}) 일부는 동일한 URL을 요청하는 초기화 함수
에 호출 을 넣고 싶습니다 . 때로는 이러한 초기화 함수 중 하나를 호출해야하며 때로는 여러 개를 호출합니다.

따라서 특정 URL이 이미로드 된 경우 서버에 대한 요청을 최소화하고 싶습니다.

나는 내 자신의 솔루션을 굴릴 수 있지만 (어려움이 있습니다!), 이것을 수행하는 표준 방법이 있는지 알고 싶습니다.



답변

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

여기서 작업하는 바이올린

편집 :이 게시물이 인기를 얻음 에 따라 시간 초과 캐시를 관리하려는 사람들에게 더 나은 답변이 있으며 $ .ajaxPrefilter ()를 사용할 때 $ .ajax () 의 모든 엉망으로 귀찮게 할 필요가 없습니다. . 이제 설정만으로 캐시를 올바르게 처리 할 수 ​​있습니다.{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와 함께 작동하지 않습니다.

다음은 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
            });
        });
    });
});

Fiddle HERE
일부 문제, 캐시 ID는 json2 lib JSON 객체 표현에 따라 다릅니다.

콘솔보기 (F12) 또는 FireBug를 사용하여 캐시에서 생성 된 일부 로그를보십시오.


답변

내 phonegap 앱 스토리지에 대한 캐싱을 찾고 있었고 @TecHunter의 답변을 찾았지만 localCache.

나는 localStorage가 ajax 호출에 의해 반환 된 데이터를 캐시하는 또 다른 대안임을 발견하고 알게되었습니다. 그래서 저는 캐싱 대신 localStorage사용하고자하는 다른 사람들에게 도움이 될 하나의 데모를 만들었습니다 .localStoragelocalCache

Ajax 호출 :

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

다른 사람들에게 도움이되기를 바랍니다!


답변

모든 최신 브라우저는 스토리지 API를 제공합니다. 그것들 (localStorage 또는 sessionStorage)을 사용하여 데이터를 저장할 수 있습니다.

응답을받은 후 브라우저 저장소에 저장하기 만하면됩니다. 그런 다음 다음에 동일한 통화를 찾을 때 응답이 이미 저장되어 있는지 검색하십시오. 그렇다면 거기에서 응답을 반환하십시오. 새로운 전화를 걸지 않으면.

Smartjax 플러그인도 비슷한 작업을 수행합니다. 그러나 요구 사항은 호출 응답을 저장하는 것이므로 jQuery ajax 성공 함수 내에 코드를 작성하여 응답을 저장할 수 있습니다. 그리고 전화를 걸기 전에 응답이 이미 저장되어 있는지 확인하십시오.


답변

귀하의 질문을 이해했다면 여기에 해결책이 있습니다.

    $.ajaxSetup({ cache: true});

및 특정 통화

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

반대 (특정 호출에 대한 캐시)를 원하면 처음에 false를 설정하고 특정 호출에 대해 true를 설정할 수 있습니다.


답변

오래된 질문이지만 내 솔루션은 약간 다릅니다.

사용자에 의해 트리거되는 아약스 호출을 지속적으로 수행하는 단일 페이지 웹 앱을 작성하고 있었고이를 더욱 어렵게 만들기 위해 jquery 이외의 메서드 (dojo, 기본 xhr 등)를 사용하는 라이브러리가 필요했습니다. 내 라이브러리 중 하나에 대한 플러그인 을 작성하여 ajax 호출에 사용 된 라이브러리에 관계없이 모든 주요 브라우저에서 작동하는 방식으로 가능한 한 효율적으로 ajax 요청을 캐시했습니다.

이 솔루션은 jSQL (내가 작성한-indexeddb 및 기타 dom 저장 방법을 사용하는 자바 스크립트로 작성된 클라이언트 측 영구 SQL 구현)을 사용하며 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();

여기에 링크 설명 입력


답변