localstorage存储

define(function() {
    var win = window,
        doc = document,

        decode = function(s) {
            // 参考jquery cookie的实现: https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js
            if (s.indexOf('"') === 0) {
                s = s.slice(1, - 1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
            }
            try {
                return decodeURIComponent(s);
            } catch (e) {
                return null;
            }
        },
        encode = encodeURIComponent,

        isSupportLocalStorage = (function() {
            try {
                var support = 'localStorage' in win && win['localStorage'] !== null,
                    test = {
                        k: 'test key',
                        v: 'test value'
                    };
                if (support) {
                    localStorage.setItem(test.k, test.v);
                    support = test.v === localStorage.getItem(test.k);
                }
                return support;
            } catch (e) {
                return false;
            }
        }()),

        stringify = function(v) {
            if (!_.isString(v)) {
                v = JSON.stringify(v);
            }
            return encode(v);
        },

        validateCookieName = function(name) {
            if (!_.isString(name) || name === '') {
                throw new TypeError('Cookie name must be a non-empty string!');
            }
        },

        // TODO: 不支持localStorage时换用cookie存储
        // 现在在某些浏览器下可能存在cookie数量的限制
        // 之后可能的优化是使用subcookie的方式: https://developer.yahoo.com/yui/cookie/#subcookies
        s = isSupportLocalStorage ? localStorage : {
            setItem: function(k, v, days) {
                validateCookieName(k);

                // 默认cookie中的结果缓存7天
                days = days || 7;
                var expires = new Date();
                expires.setDate(expires.getDate() + days);

                v = _m.utils.evaluate(v);
                if (_.isArray(v)) {
                    v = v[0];
                    expires = new Date(parseInt(v[1], 10));
                }

                k = stringify(k);
                v = stringify(v);

                // 高端浏览器中一般合并字符用+比用join('')更高效
                // 参考: http://photo.weibo.com/2785671884/wbphotos/large/photo_id/3453950944633013?refer=weibofeedv5
                doc.cookie = k + '=' + v + '; expires=' + expires.toGMTString();
            },

            getItem: function(k) {
                validateCookieName(k);

                k = stringify(k) + '=';

                var v = null,
                    cookie = doc.cookie,
                    start = cookie.indexOf(k);

                if (start > -1) {
                    var end = cookie.indexOf(';', start);
                    if (end === -1) {
                        end = cookie.length;
                    }
                    v = decode(cookie.substring(start + k.length, end));
                }

                return v;
            },

            removeItem: function(k) {
                this.setItem(k, '', - 1);
            }
        },

        prefix = '_BM:';

    return {
        isSupportLocalStorage: isSupportLocalStorage,

        set: function(k, v, expires) {
            if (_.isNumber(expires)) {
                expires = +new Date() + expires;
            }
            s.setItem(prefix + k, JSON.stringify({
                value: v,
                expires: expires
            }));
        },

        get: function(k) {
            var v = JSON.parse(s.getItem(prefix + k)),
                expires;

            if (!v) {
                return;
            }

            expires = parseInt(v.expires, 10);
            v = v.value;

            if (expires) {
                if (+new Date() < expires) {
                    return v;
                }
                this.remove(k);
            }

            return v;
        },

        remove: function(k, v) {
            if (v) {
                try {
                    this.set(k, _.difference(this.get(k), v));
                } catch (e) {}
            } else {
                s.removeItem(prefix + k);
            }
        },

        add: function(k, v, options) {
            var h = this.get(k),

                defaults = {
                    type: 'set',
                    limit: 10
                },
                opts = _.extend(defaults, options),

                type = opts.type,
                expires = opts.expires,
                limit = opts.limit;

            // TODO: 有潜在的bug, 比如之前存储的是array类型
            if (!_.isArray(h)) {
                h = _.isUndefined(h) && [] || [h];
            }

            if (type === 'set' && _.indexOf(h, v) !== -1) {
                return;
            }

            if (_.isNumber(limit) && limit > 0) {
                h = _.first(h, limit - 1);
            }

            h.unshift(v);

            this.set(k, h, expires);
        }
    };
});
 

你可能感兴趣的:(存储,localStorage)