localStorage 存满了怎么办?

先来几道面试题

1、a.meituan.com 和 b.meituan.com 这两个域能够共享同一个 localStorage 吗?

2、在 webview 中打开一个页面:i.meituan.com/home.html,点击一个按钮,调用 js 桥打开一个新的 webview:i.meituan.com/list.html,这两个分属不同 webview 的页面能共享同一个 localStorage 吗?

3、如果 localStorage 存满了,再往里存东西,或者要存的东西超过了剩余容量,会发生什么?

答案

1、同一个域名(document.domain)共享同一个 localStorage,a.meituan.com 和 b.meituan.com 是两个域名,所以不能共享

2、能。相当于同一个浏览器的不同标签页。不同浏览器之间不能共享。

3、存不进去并报错(QuotaExceededError)

理想的方案

假设我们回到起点,从零建设前端工程,我们怎么避免 localStorage 存满的问题?

1、划分域名。各域名下的存储空间由各业务组统一规划使用

2、跨页面传数据:考虑单页应用、优先采用 url 传数据

3、最后的兜底方案:清掉别人的存储

互相伤害其实是个好办法

在已然发展很久的业务中,我们怎么解决此问题呢?

const QUOTA_EXCEEDED_ERR_CODE = 22
function write (key, data) {
    try {
        localStorage.setItem(key, data);
    } catch (e) {
        if (e.code === QUOTA_EXCEEDED_ERR_CODE) {
            localStorage.clear();
            localStorage.setItem(key, data);
        }
    }
}

上面这个方法还是有点问题,因为它把自己业务要用的东西也给删了,所以自己的业务最好统一在 key 上加一个前缀,清空 localStorage 时只删别人的。

有的同学可能会担心,这样会不会对其它业务造成伤害?或者产生一些难以发现的 bug。其实这种担心很大程度上是因为忽略了实际的使用场景。用户用同一个设备打开同一个 app,在同一个时间只能访问一个业务,因此不会存在某个业务正在使用过程中,localStorage 被其它业务清掉的场景,除非!除非有交叉的业务场景。

一、如何得到localStorage已使用容量

(function(){
    if(!window.localStorage) {
        console.log('浏览器不支持localStorage');
    }
    var size = 0;
    for(item in window.localStorage) {
        if(window.localStorage.hasOwnProperty(item)) {
            size += window.localStorage.getItem(item).length;
        }
    }
    console.log('当前localStorage已使用容量为' + (size / 1024).toFixed(2) + 'KB');
})()

二、如何获取localStorage最大容量

通过上面的分析,其实思路基本是一样的,都是通过字符长度来判断。

(function() {
   if(!window.localStorage) {
   console.log('当前浏览器不支持localStorage!')
   }    var test = '0123456789';
   var add = function(num) {
     num += num;
     if(num.length == 10240) {
       test = num;
       return;
     }
     add(num);
   }
   add(test);
   var sum = test;
   var show = setInterval(function(){
      sum += test;
      try {
       window.localStorage.removeItem('test');
       window.localStorage.setItem('test', sum);
       console.log(sum.length / 1024 + 'KB');
      } catch(e) {
       console.log(sum.length / 1024 + 'KB超出最大限制');
       clearInterval(show);
      }
   }, 0.5)
 })()

注:上面代码可能卡死浏览器

相关链接:

https://www.cnblogs.com/kidney/p/9058352.html

https://www.cnblogs.com/MonkeyKingK/p/5499831.html

posted @ 2018-12-28 20:46  笠航  阅读(2511)  评论(0编辑  收藏  举报