Storage 封装
  8CtDmU74qicX 2023年11月24日 20 0

一 JSON - javascript Object Notation(符号) 基于JavaScript原生语法,能够序列化对象、数组、数值、字符串、布尔值和 null。

JSON.parse(s,(key,value)=>{

console.log(key,value);

// s 为字符串 '"字符"' 或者 '数字' 、'null' 、'{}'、'[]' key 都为空,value 为其解析的值

// s 为JSON对象字符串,key 和 value 才为其解析的值

// undefined、Symbol和BigInt,数字也不支持NaN、Infinity和-Infinity,都会报错

});

JSON.parse();

JOSN.parse 解析 非数字字符串, 必须为这种格式  '"abc"' ,  如果为 'abc' 会抛出异常;

JSON.pase 解析 数字字符串,'2343' , 'null' ,'true' , '{}', '[]' 解析为原来的值。JSON.stringify();

JSON.stringify(v,(key,value)=>{

// 用来处理 value 为undefined ,如果为undefined 或者函数 则会将该项取消,不会展示

if(value === undefined || typeof value === 'function'){

return null;

}

return value;

缩进);

// JSON.stringify( undefined, function, Bigint, Symbol 等 ) 结果都为undefined ,注意不是字符串的undefined

注意:localStorage 存 数字,最后取出来依旧为字符串。需要把起包裹在一个对象内。或者使用JSON.stringify 进行存储。
注意:当对象的层级过深,数量级很大时候,执行JSON.parse 和 JSON.stringify 的时候 会递归去进行类型的判断和转化,就会很耗时。
优化的做法是,使用 fast-json-stringify 和 fast-json-parse

localStorage/ sessionStorage / indexDB
sessionStorage : 打开多个 相同URL 的 Tabs 页面,会创建 各自 的 sessionStorage 内存空间,而 localStorage会 共用一个内存空间。
storage 下的方法
setItem()
removeItem()
getItem()
clrear()

封装注意点

  1. 传入的是 sessionStorage 还是 localStorage , 因为这两个 在方法上是一致的。
  2. nameSpace 命名空间,是否使用同一个命名空间,某个项目下。通过一个参数来判断,默认是使用。
  3. 是否通过一个队列来异步存取。性能分析,localStorage 中 进行存取其实是非常快的,因为都是存取的字符串。但是JSON.stringify 复杂的对象会很慢。
  4. 尽量不要把所有数据都存到一个命名空间内,特别是 有大数据的时候。将其写成单独的一个空间内。
  5. 支持异步存取。写一个队列,存入先放入队列中,过一段时间的延迟再存入缓存中。 所以取的时候,也要先去队列中去取。 (所以定义某个数据的存取,需要写函数进行,不然你根本无法预料其他人是怎么去存取的数据,无法控制)。 - 放弃,因为相当于只做了一个防抖操作。
  6. 大数据放到 indexDB 中去
  7. fastJSON
  8. 支持 fastJSON + TS 方法 (库:fastJsonParse, faseJsonStringify)

localStorage 的读取性能 和 存入的 字符串长度关系 ?读取的性能非常强,存入10万个字符 和 存入 1个字符 的时间都很快,几乎可以忽略不计。
所以,localStorage 慢的原因,只是 JSON 的序列化和反序列化慢。

需求 - 只能使用SDK 提供的方式进行读取缓存
代理模式 的扩展 思想
先缓存一下,原生的 setItem 和 getItem 函数。然后直接将 localStorage.setItem = null
在封装的缓存内部,调用setItem.apply( localstorage,[key, value] )
其他方式也是一样的,比如,直接重写 window.console.log 函数,在其内部判断是否配置了某个参数,只有在配置了才能正常打印。保证线上环境不会出现console 打印。

如何知道local的大小,利用字符串转 Blob 后的length 可大致计算出。

function countStringSize(str:string){

return new Blob([str]).length;

}

开始编写 LocalStorage
判断 浏览器是否支持

function isObj(v) {

return typeof v === 'object' && v !== null;

}

export class CacheStorage {

private isSupport: boolean;

private storage: Storage;

private nameSpace: string;

private type: string;

constructor(type: 'localStorage' | 'sessionStorage', nameSpace: string) {

this.type = type;

this.storage = window[type];

this.nameSpace = nameSpace;

this.isSupport = window[type] !== undefined;

}

countStorageSize(): number {

const length = this.storage.length;

const keys = Object.keys(this.storage);

let size = 0;

for (let i = 0; i < length; i++) {

const blob = new Blob([keys[i]]);

size += blob.size;

}

return size;

}

setItem(key: string, value: unknown, isNameSpace = true): void {

if (value === undefined) {

value = null;

}

let lKey, lValue;

if (isNameSpace) {

lKey = this.nameSpace;

const valueString = localStorage.getItem(this.nameSpace);

let obj;

if (valueString) {

obj = JSON.parse(valueString);

if (isObj(obj)) {

obj[key] = value;

}

} else {

obj = {};

obj[key] = value;

}

lValue = JSON.stringify(obj);

} else {

lKey = key;

lValue = JSON.stringify(value);

}

try {

this.storage.setItem(lKey, lValue);

} catch (e) {

if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {

console.warn(this.type + 'Storage 存储已达上限!');

}

// 现在不管什么报错,都执行清空操作

this.storage.clear();

}

}

getItem(key: string, isNameSpace = true): T {

if (!isNameSpace) {

const str = this.storage.getItem(key);

return JSON.parse(str);

}

const value = this.storage.getItem(this.nameSpace);

return JSON.parse(value)?.[key];

}

removeItem(key: string, isNameSpace = true): void {

if (!isNameSpace) {

return this.storage.removeItem(key);

}

const value = JSON.parse(this.storage.getItem(this.nameSpace));

Reflect.deleteProperty(value, key);

this.storage.setItem(this.nameSpace, JSON.stringify(value));

}

clear(isNameSpace = true): void {

if (!isNameSpace) {

return this.storage.clear();

}

return this.storage.removeItem(this.nameSpace);

}

}

使用indexDB库。由于indexDB的存取是异步的,且不需要进行JSON 数据格式的转化,所以理论上效率比存localStorage 还要高。
使用 indexDB 库 -

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月24日 0

暂无评论

推荐阅读
8CtDmU74qicX