如何使用localstorage代替cookie实现跨域共享数据问题

2019-01-28 21:06:18于丽

3,postHandle方法,在发送请求前包装data,生成cbid,origin,action和args,cbs对象保存了每个cbid下的resolve和reject,等待子页面的postMessage返回后处理。因为postMessage不能保留引用,不能传函数,所以这里选择这个方法来进行关联。

4,constructor比较好理解,当这个类被初始化的时候,我们定义了我们需要的一些options的属性,创建iframe,然后监听message事件,处理子页面返回的消息。

5,在父页面的message事件中,我们要校验,给我发消息的必须是我打开的这个窗口iframe,否则报错,然后根据data中的err标识来让cbs中的resolve和reject进行执行。

6,createIframe方法中,iframe onload中的回调处理创建前 缓存的调用方法,这里注意使用了domready,因为可能body还没解析就会进行sdk的执行。

下面是child部分的代码:

class iframe { set(key, val, options, origin) { //检查val大小,不能超过20k. val = val.toString(); val = this.lz ? lzstring.compressToUTF16(val) : val; var valsize = sizeof(val, 'utf16'); //localStorage 储存使用utf16编码计算字节 if (valsize > this.maxsize) { return { err: 'your store value : "' + valstr + '" size is ' + valsize + 'b, maxsize :' + this.maxsize + 'b , use utf16' } } key = `${this.prefix}_${key},${new url(origin).origin}`; var data = { val: val, lasttime: Date.now(), expire: Date.now() + options.expire }; store.set(key, data); //大于最大储存个数,删除最后一次更新的 if (store.size() > this.storemax) { var keys = store.keys(); keys = keys.sort((a, b) => { var item1 = store.get(a), item2 = store.get(b); return item2.lasttime - item1.lasttime; }); var removesize = Math.abs(this.storemax - store.size()); while (removesize) { store.remove(keys.pop()); removesize--; } } return { ret: data } } get(key, options) { var message = {}; var keys = store.keys(); var regexp = new RegExp('^' + this.prefix + '_' + key + ',' + options.domain + '$'); message.ret = keys.filter((key) => { return regexp.test(key); }).map((storeKey) => { var data = store.get(storeKey); data.key = key; data.domain = storeKey.split(',')[1]; if (data.expire < Date.now()) { store.remove(storeKey); return undefined; } else { //更新lasttime; store.set(storeKey, { val: data.val, lasttime: Date.now(), expire: data.expire }); } data.val = this.lz ? lzstring.decompressFromUTF16(data.val) : data.val; return data; }).filter(item => { return !!item; //过滤undefined }); return message; } clear(key, origin) { store.remove(`${this.prefix}_${key},${origin}`); return {}; } clearOtherKey() { //删除不合法的key var keys = store.keys(); var keyReg = new RegExp('^' + this.prefix); keys.forEach(key => { if (!keyReg.test(key)) { store.remove(key); } }); } constructor(safeDomain, lz) { supportCheck(); this.safeDomain = safeDomain || /.*/; this.prefix = '_cros'; this.clearOtherKey(); if (Object.prototype.toString.call(this.safeDomain) !== '[object RegExp]') { throw new Error('safeDomain must be regexp'); } this.lz = lz; this.storemax = 100; this.maxsize = 20 * 1024; //字节 addEvent(window, 'message', (evt) => { var data = JSON.parse(evt.data); var originHostName = new url(evt.origin).hostname; var origin = evt.origin, action = data.action, cbid = data.cbid, args = data.args; //合法的广播 if (evt.origin === data.origin && this.safeDomain.test(originHostName)) { args.push(origin); var whiteAction = ['set', 'get', 'clear']; if (whiteAction.indexOf(action) > -1) { var message = this[action].apply(this, args); message.cbid = cbid; window.top.postMessage(JSON.stringify(message), origin); } } else { window.top.postMessage(JSON.stringify({ cbid: cbid, err: 'Illegal domain' }), origin); } }); } }