黑马程序员技术交流社区

标题: LocalStroage 内存不足的解决方案? [打印本页]

作者: 透露姓名的网民    时间: 2019-10-25 15:49
标题: LocalStroage 内存不足的解决方案?
localStorage这个特性主要是用来作为本地存储来使用的,一般浏览器支持的是5M大小。如果不够用
就要考虑给localStorage扩容。
扩容思路如下:
1.在A域下引入B域,A域空间足够时,读写由A域完成,数据存在A域。当A域内存不够时,读写
由B域完成,数据存在B域下。
2.A域空间不够需要B域读写时,通过postMessage向B域发送跨域消息,B域监听跨域消息,在
接收到指定消息时进行读写操作
3.B域接到跨域消息时,如果是写入或者删除可以什么都不做,如果是读取,就要先读取本域本地数据
通过postMessage向父页面发送消息
4.A域在读取B域的数据时需要监听来自B域的跨域消息
注意事项:
在发送消息之前,应该先获取到要发送的窗口,这样才能成功发送消息。
1.A域向B域发消息,应用window.frames[0].postMessage() ,这样iframe内的B域才可以接到
2.同理,B域向 A域发消息时应用,window.parent.postMessage()
3.A域的逻辑一定要在iframe加载完成后进行
A域页面如下:
[HTML] 纯文本查看 复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
    <title></title>
    </head>
    <body>
        <button class="set">存储</button>
        <button class="get">读取</button>
        <button class="remove">删除</button>
        <iframe src="http://localhost:8000/storage.html"></iframe>   //嵌入【B域】的一个空页面
    </body>
    <script src="js/localStorage.js"></script>
</html>

由于需要判断【A域】的空间是否足够,所以需要计算【A域】已经被占用的空间。那么localStorage中的字符串以什么编码格式存储的呢?
经过反复试验发现,当使用utf-16的编码方式进行计算时,当存储的字符串大于5M时,浏览区就会报错:字符串大小超过最大值。
所以localStorage中的字符串是以utf-16进行编码的。
// localStorage.js如下
[JavaScript] 纯文本查看 复制代码
/*这段代码是用来测试localStorage中字符串的编码格式*/
/**
* 计算字符串所占的内存字节数,默认使用UTF-8的编码方式计算,也可制定为UTF-16
* UTF-8 是一种可变长度的 Unicode 编码格式,使用一至四个字节为每个字符编码
*
* 000000 - 00007F(128个代码)      0zzzzzzz(00-7F)                             一个字节
* 000080 - 0007FF(1920个代码)     110yyyyy(C0-DF) 10zzzzzz(80-BF)             两个字节
* 000800 - 00D7FF
00E000 - 00FFFF(61440个代码)    1110xxxx(E0-EF) 10yyyyyy 10zzzzzz           三个字节
* 010000 - 10FFFF(1048576个代码)  11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz  四个字节
*
* 注: Unicode在范围 D800-DFFF 中不存在任何字符
*
* UTF-16 大部分使用两个字节编码,编码超出 65535 的使用四个字节
* 000000 - 00FFFF  两个字节
* 010000 - 10FFFF  四个字节
*
* @param  {String} str
* @param  {String} charset utf-8, utf-16
* @return {Number}
*/

function sizeof(str,charset){
    var strCode=0,charCode;
    charset = charset?charset.toLowerCase():'';
    if(charset=='utf-16'||charset=='utf16'){
        for(var i=0,len=str.length;i<len;i++){
            charCode = str.charCodeAt(i);
            strCode += charCode<0xffff?2:4;
        }
    }else{
        for(var i=0,len=str.length;i<len;i++){
            charCode = str.charCodeAt(i);
            strCode += (charCode<0x007f&&1)||(charCode<0x07ff&&2)||(charCode<0xffff&&3)||4;
        }
    }
    return strCode/1024/1024/2;
}
/*测试localStorage中字符串的编码格式结束*/

function storage(type,key,value){
    var val = localStorage.getItem(key);
    switch (type){
        case 'get':
            if(val){
                return val;
            }else{
                return window.frames[0].postMessage(JSON.stringify({type:type,key:key}),'http://localhost:8000');
            }
            break;
        case 'set':
            if(!val&&sizeofLocal()+sizeof(value)>5){
                            window.frames[0].postMessage(JSON.stringify({type:type,key:key,value:value}),'http://localhost:8000');

            }else{
                localStorage.setItem(key,value);
            }
        break;
        case 'remove':
            if(val){
                localStorage.removeItem(key);
            }else{
                window.frames[0].postMessage(JSON.stringify({type:type,key:key}),'http://localhost:8000');   
            }
            break;
        default:
            break;
    }
}

function sizeofLocal(){
    var myStr = '',charCode,strCode=0;
    for(item in localStorage){
        if(localStorage.hasOwnProperty(item)){
            myStr += localStorage.getItem(item);
        }
    }
    for(var i=0,len=myStr.length;i<len;i++){
        charCode = myStr.charCodeAt(i);
        strCode += charCode<0xffff?2:4;
    }
    return strCode/1024/1024/2;
}

var myStr='';
for(var i=0;i<1024*1200;i++){
    myStr += 1+'12'+'啦';
}

document.querySelector(".set").onclick = function(){
    storage("set","yoyo",myStr);
}

document.querySelector(".get").onclick = function(){
    storage("get","yoyo");
    window.addEventListener('message',function(e){
        window.myStorage = e.data;  
    })
}

document.querySelector(".remove").onclick = function(){
    storage("remove","yoyo");
}

B域页面如下:
[HTML] 纯文本查看 复制代码
storage.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>

</body>
<script type="text/javascript">
    var fn = function(){};
    fn.prototype = {
        setLocal:function(key,value){
            localStorage.setItem(key,value);
        },
        getLocal:function(key){
            return localStorage.getItem(key);
        },
        removeLocal:function(key){
            localStorage.removeItem(key);
        },
        bindEvent:function(){
            var self = this;
            //监听
            window.addEventListener('message',function(e){
                if(window.parent!=e.source) return;
                var option = JSON.parse(e.data);
                if(option.type.toLowerCase()=="get"){
                    var data = self.getLocal(option.key);
                    window.parent.postMessage(data,'*');
                }
                option.type.toLowerCase()=="set"&&self.setLocal(option.key,option.value);
                option.type.toLowerCase()=="remove"&&self.removeLocal(option.key);
            })
        },
        init:function(){
            var self = this;
            self.bindEvent();
        }
    }
    var tools = new fn();
    tools.init();
</script>




链接:https://www.cnblogs.com/cherishSmile/p/8390754.html
作者: 梦缠绕的时候    时间: 2019-10-31 16:31
加油~你们是好样的,nice
作者: 晨大喵    时间: 2019-10-31 16:32
加油加油
作者: 放荡的人生    时间: 2019-10-31 16:42
加油~少年,nice
作者: 魔都黑马少年梦    时间: 2019-10-31 16:46
加油少年~
作者: xiaowang66    时间: 2019-10-31 17:08
加油哦
作者: 梦缠绕的时候    时间: 2019-11-7 16:30
unimaginable,加油~
作者: 放荡的人生    时间: 2019-11-7 16:46
很好,棒
作者: xiaowang66    时间: 2019-11-7 16:58
加油呀
作者: 小影姐姐    时间: 2019-11-14 16:55
未来可期,前途无限,让我们一起加油!!!
作者: 放荡的人生    时间: 2020-3-26 17:00
好的真的很厉害




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2