乐道

乐在其中,道不出口

 

使用cookie作对象持久化

个人首先是非常不推荐使用cookie作对象持久化的,因为cookie在每次request请求中都会带上,无形就增加了请求的大小。

如果对cookie的domain没有管理好,问题会更大,如所有domain.com下的cookie,在你请求js.domain.com或img.domain.com也都会带上,但这些域下的cookie是毫无意义的;所以很多网站会使用其他域名如jsdomain.com或imgdomain.com以减小cookie对请求的开销。

已有的工具:jquery.jsoncookie.js(可参考http://lab.distilldesign.com/json-cookie/),这个插件依赖于jquery.cookie.js,如果浏览器不支持JSON的方法,你或许还需要一个json2.js。

 

那为什么不直接用这个插件,我们先看个例子:

对象: {id: 123, name: "mapping", test: "Hello World"}

先转成字符串,使用JSON.stringify: '{"id":123,"name":"mapping","test":"Hello World"}'  length:48

再转成URI Encode,使用encodeURIComponent: '%7B%22id%22%3A123%2C%22name%22%3A%22mapping%22%2C%22test%22%3A%22Hello%20World%22%7D'  length:84

可以看到经过转码后的json字符串长度几乎翻倍,是因为浏览器为了安全考虑,会将{、"、,等这些特殊符号进行转义编码。

 

如果使用上方插件必然会增加cookie的开销,那我们就需要尽量避免cookie的内容被转码,可以考虑使用-、_、.这些字符,使用"."可能会跟数据的小数点冲突,但实际情况多是用cookie记录id的整数,所以也可以考虑

CookieString = {
        setting: {
            groupfix: '_',
            childfix: '-',
            itemfix: '.'
        },
        stringify: function(obj) {
            var t = this, groups = [], 
                isArray = function(ar) {
                    return Object.prototype.toString.call(ar) === '[object Array]';
                }, o, items;
            if(isArray(obj)) {
                groups = obj;
            } else {
                for(o in obj) {
                    if(obj.hasOwnProperty(o)) {
                        items = obj[o];
                        if(isArray(obj[o])) {
                            items = items.join(t.setting.itemfix);
                        }
                        groups.push(o + t.setting.childfix + items);
                    }
                }
            }
            return groups.join(t.setting.groupfix);
        },
        parse: function(str) {
            var t = this, groups = str.split(t.setting.groupfix),
                o, c, i, obj = false;
            if(str.indexOf(t.setting.childfix) !== -1) {
                obj = {};
            } else {
                obj = [];
            }
            for(o in groups) {
                c = groups[o].split(t.setting.childfix);
                if(c[1] === undefined) {
                    obj.push(c[0]);
                } else {
                    i = c[1].split(t.setting.itemfix);
                    obj[c[0]] = i.length === 1 ? i[0] : i;
                }
            }
            return obj;
        }
    };

来看一下测试结果,这里推荐使用qunit作为测试框架。tips:如果需要在页面中看到测试结果,记得加一个<div id="qunit"></div>的节点

test('CookieString.stringify', function() {
        equal(CookieString.stringify({1:[1,2,3], 2:4}), '1-1.2.3_2-4', 'stringify object');
        equal(CookieString.stringify([1,2,3,4]), '1_2_3_4', 'stringify array');
    });
    test('CookieString.parse', function() {
        deepEqual(CookieString.parse('1-1.2.3_2-4'), {1:['1','2','3'], 2:'4'}, 'parse object');
        deepEqual(CookieString.parse('1_2_3_4'), ['1','2','3','4'], 'parse object');
    });

测试通过了^_^

对象已经可以成功转为字符串了,接下来可以借助jquery.cookie.js读写cookie;

 

慢着,事情还没有结束,这样子后端要解析cookie的值不会像转下json那么简单了,但如果在项目中约定好cookie的格式,后端写好解析该格式的公用库也会得心应手的。

ps:使用开源库确实可以节省不少开发时间,但也会增加很多额外开销;用和不用没有对错之分,只有合适与不合适,如果感觉不合适,那就自己乖乖写吧~~

posted on 2012-11-16 00:35  乐道  阅读(2666)  评论(2编辑  收藏  举报

导航