javascript数据缓存策略之本地存储

昨天看了司徒正美的博客http://www.cnblogs.com/rubylouvre/archive/2012/09/14/2684061.html讲到一个很完美的文件加载方案,思考很久,收益颇深。他考虑的很全面,但是美中不足的是并没有考虑ie6、7的情况,ie6、7下单个文件最大值能存64K,很多大文件是无法加载的,尤其是新版的jquery。

 

如果把这个思路再扩展一下,放到数据缓存里面来,将是一个很完美的解决方案。

 

我们先完成一个本地存储的DB类。

db = function() {

    var store = window.localStorage, doc = document.documentElement;

    if (!store) {

        doc.style.behavior = 'url(#default#userData)';

    }

    return {

        /**

         * 保存数据

         */

        set : function(key, val, context) {

            if (store) {

                return store.setItem(key, val, context);

            } else {

                doc.setAttribute(key, value);

                return doc.save(context || 'default');

            }

        },

        /**

         * 读取数据

         */

        get : function(key, context) {

            if (store) {

                return store.getItem(key, context);

            } else {

                doc.load(context || 'default');

                return doc.getAttribute(key) || '';

            }

        },

        /**

         * 删除数据

         * @param {Object}

         * @param {Object}

         */

        rm : function(key, context) {

            if (store) {

                return store.removeItem(key, context);

            } else {

                context = context || 'default';

                doc.load(context);

                doc.removeAttribute(key);

                return doc.save(context);

            }

        },

        /**

         * 清空数据

         */

        clear : function() {

            if (store) {

                return store.clear();

            } else {

                doc.expires = -1;

            }

        }

    };

}();

 

然后我们再写一个简单的ajax函数。

 

if ( typeof window.XMLHttpRequest === "undefined") {

    window.XMLHttpRequest = function() {

        return new window.ActiveXObject(navigator.userAgent.indexOf("MSIE 5") >= 0 ? "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP");

    };

}

ajax = function(uri, options) {

    var httpRequest, httpSuccess, timeout, isTimeout = false, isComplete = false, noop = function() {

    };



    options = {

        method : options.method || "GET",

        data : options.data || null,

        arguments : options.arguments || null,



        onSuccess : options.onSuccess || noop,

        onError : options.onError || noop,

        onComplete : options.onComplete || noop,

        onTimeout : options.onTimeout || noop,

        isAsync : options.isAsync || true,

        timeout : options.timeout ? options.timeout : 30000,

        contentType : options.contentType ? options.contentType : "utf-8",

        type : options.type || "xml"

    };

    uri = uri || "";

    timeout = options.timeout;



    httpRequest = new window.XMLHttpRequest();

    httpRequest.open(options.method, uri, options.isAsync);

    //设置编码集

    httpRequest.setRequestHeader("Content-Type", options.contentType);



    /**

     * @ignore

     */

    httpSuccess = function(r) {

        try {

            return (!r.status && location.protocol == "file:") || (r.status >= 200 && r.status < 300) || (r.status == 304) || (navigator.userAgent.indexOf("Safari") > -1 && typeof r.status == "undefined");

        } catch(e) {

        }

        return false;

    }

    /**

     * @ignore

     */

    httpRequest.onreadystatechange = function() {

        if (httpRequest.readyState == 4) {

            if (!isTimeout) {

                var o = {};

                o.responseText = httpRequest.responseText;

                o.responseXML = httpRequest.responseXML;

                o.data = options.data;

                o.status = httpRequest.status;

                o.uri = uri;

                o.arguments = options.arguments;



                if (httpSuccess(httpRequest)) {

                    if (options.type === "script") {

                        eval.call(window, data);

                    }

                    options.onSuccess(o);



                } else {

                    options.onError(o);

                }

                options.onComplete(o);

            }

            isComplete = true;

            //删除对象,防止内存溢出

            httpRequest = null;

        }

    };



    httpRequest.send(options.data);



    window.setTimeout(function() {

        var o;

        if (!isComplete) {

            isTimeout = true;

            o = {};

            o.uri = uri;

            o.arguments = options.arguments;

            options.onTimeout(o);

            options.onComplete(o);

        }

    }, timeout);



    return httpRequest;

};

 

好了,最后说一下解决方案,源码如下:

 

var cacheData = {};

cache = function(url, func, cacheTime) {

    //先读内存

    if(cacheData[url]){

        func.call(this, cacheData[url]);

        return;

    }else{

        var me = this,

        chData = db.get(url), 

        chTime = db.get(url + "__time"), 

        now = new Date().getTime(), 

        cacheTime = cacheTime || 60, 

        ct = now - 60000 * cacheTime, //默认缓存时间为1个小时

        success = function(data) {

            var res = data.responseText;

            cacheData[url] = res;

            db.set(url, res);

            db.set(url + "__time", now);

            func.call(me, res);

        };

        //存在数据的情况

        if (chData && chTime) {

            //未过期的情况

            if (ct < chTime) {

                func.call(this, chData);

            } else {//过期的情况

                ajax(url, {'onSuccess' : success});

            }

        } else {

            ajax(url, {'onSuccess' : success});

        }

    }

    

}

 

over。

 

 

你可能感兴趣的:(JavaScript)