代码也不多,这里简单说一下各个方法的用处和组织关系:
1,constructor部分,上面的类里也进行浏览器特性支持检查,然后定义了store的prefix值,最大个数和每一个key的maxsize等属性。然后我们创建message通道,等待父页面调用。
2,在message中,我们对发送广播的origin进行检查,然后对调用的方法进行检查,调用对应的set,get,clear方法,然后把执行的结果拿到,绑定cbid,最后再postMessage发送回父页面。
3,clearOtherKey 删除不合法的一些store数据,只保留符合格式的数据。
4,set方法中对每一条的数据做size校验,lz压缩,保存的data中包含了val,key,过期时间以及更新时间(用于LRU计算)。
5,set方法中,如果储存的ls个数超过了最大限制,这个时候需要进行删除操作, LRU是Least Recently Used的缩写,即最近最少使用。我们通过遍历所有的key值,对key值做一个排序,通过lasttime,然后进行keys数组的pop操作,拿到堆栈尾部的需要被清除的key,然后逐个删除。
6,get方法中,我们通过遍历所有的key值,匹配到我们需要拿到的domain的域的key,然后把返回值中的key进行拆解(我们储存时是 key,domain的格式),因为api要求返回多个符合的值,我们对过期的数据最后再做一个filter,然后使用lz解压缩val值,保证用户拿到的是正确结果。
以上就是我们的一个整体实现编码过程和review,下面说一说遇到的坑。
五,一些遇到的坑
因为上面只给了主代码,并不是完整代码,因为本身逻辑比较清晰,花一点时间都可以写出来的。下面说说有什么坑的地方。
1,计算localstorage的储存值。
因为我们都知道有5MB的限制,所以每一条数据最大要求不能超过20*1024 字节,对于字节的计算,localstorage要使用utf16的编码进行转换,参考这篇文章: JS计算字符串所占字节数
2,兼容性
ie8下postMessage最好都传字符串,事件需要抹平处理,JSON需要抹平处理。
3,创建iframe时的异步处理
这里之前做了个一个setTimeout的递归等待,后来更改成了上面的实现方法,通过onload后统一处理promise的reslove,保证promise api的统一。
4,数据保存时,空间复杂度 vs 时间复杂度。
第一个版本并不是上面的实现,我实现了3个版本:
第一个版本是保存了一个LRU的数组,为了减少时间复杂度,但是浪费了空间复杂度,而且经过测试,store的get方法耗时比较大,主要是parse的耗时。
第二个版本,为了能让lz-string压缩率最大化,我把所有的数据包括LRU数组保存到了一个key值上,导致数据多的时候lz-string和getItem,parse时间消耗非常大,虽然计算的时间复杂度是最低。









