给localStorage设置一个过期时间的方法分享
思考点
在web开发中,我们知道cookie、session、localStorage都可以保存用户的数据,cookie的domain、path限制了cookie的跨域,有数量和大小的限制,可以设置有效时间。session是后台在浏览器注入一个设置了httponly的不可读取的cookie,sessiondata由后台保存在数据库或者内存中,在web中,session是靠cookie作为唯一标示来实现的,也可以设置过期时间。localStorage是H5的数据存储办法,也是有大小限制的,但是不可以设置过期时间。
从我们接触前端起,第一个熟悉的存储相关的Cookie或者来分析我们生活中密切相关的淘宝、物流、闹钟等事物来说起吧,
- Cookie从你设置的时候,就会给个时间,不设置默认会话结束就过期;
 - 淘宝购物从你下单付款起,就会给这件货物设置一个收货期限时间,过了这个时间自动认为你收货(即订单结束);
 - 闹钟你设置的提醒时间,其实也就是它的过期时间;
 - 再比如与您每天切身相关的产品需求,过完需求,你给出的上线时间,也就是这个需求的过期时间;
 - 再通俗点讲,您今年的生日过完到明年生日之间也是相当于设置了有效期时间;
 
以上种种,我们能得出一个结论任何一件事、一个行为动作,都有一个时间、一个节点,甚至我们可以黑localStorage,就是一个完善的API,为什么不能给一个设置过期的机制,因为sessionStorage、Cookie并不能满足我们实际的需求。
实现思路
抱歉,黑localStorage不完善,有点夸张了,综合上述的总结,问题就简单了,给localStorage一个过期时间,一切就都soeasy?到底是不是,来看看具体的实现吧:
简单回顾
//示例一:
localStorage.setItem('test',1234567);
lettest=localStorage.getItem('test');
console.log(typeoftest,test);
//示例二:
localStorage['name']='苏南';
console.log(localStorage['name']);
/*
输出:
"1234567",'苏南',
这里要注意,1234567存进去时是number取出来就成string了
*/
重写set(存入)方法:
- 首先有三个参数key、value、expired,分别对应键、值、过期时间,
 - 过期时间的单位可以自由发挥,小时、分钟、天都可以,
 - 注意点:存储的值可能是数组/对象,不能直接存储,需要转换JSON.stringify,
 - 这个时间如何设置呢?在这个值存入的时候在键(key)的基础上扩展一个字段,如:key+'expires',而它的值为当前时间戳+expired过期时间
 
具体来看一下代码:
set(key,value,expired){
/*
*set存储方法
*@param{String}key键
*@param{String}value值,
*@param{String}expired过期时间,以分钟为单位,非必须
*@由@IT·平头哥联盟-首席填坑官∙苏南分享
*/
letsource=this.source;
source[key]=JSON.stringify(value);
if(expired){
source[`${key}__expires__`]=Date.now()+1000*60*expired
};
returnvalue;
}
重写get(获取)方法:
- 获取数据时,先判断之前存储的时间有效期,与当前的时间进行对比;
 - 但存储时expired为非必须参数,所以默认为当前时间+1,即长期有效;
 - 如果存储时有设置过期时间,且在获取的时候发现已经小于当前时间戳,则执行删除操作,并返回空值;
 - 注意点:存储的值可能是数组/对象,取出后不能直接返回,需要转换JSON.parse,
 
具体来看一下代码:
get(key){
/*
*get获取方法
*@param{String}key键
*@param{String}expired存储时为非必须字段,所以有可能取不到,默认为Date.now+1
*@由@IT·平头哥联盟-首席填坑官∙苏南分享
*/
constsource=this.source,
expired=source[`${key}__expires__`]||Date.now+1;
constnow=Date.now();
if(now>=expired){
this.remove(key);
return;
}
constvalue=source[key]?JSON.parse(source[key]):source[key];
returnvalue;
}
重写remove(删除)方法:
删除操作就简单了,;
remove(key){
constdata=this.source,
value=data[key];
deletedata[key];
deletedata[`${key}__expires__`];
returnvalue;
}
优化点:
- 记得上次有个同学,是这么评论的:「删除缓存能放到constructor里面执行么,放到get里面不取就一直在那是不是不太好?」;
 - 为什么不用forin而是for?forin循环遍历对象的属性时,原型链上的所有属性都将被访问,解决方案:使用hasOwnProperty方法过滤或Object.keys会返回自身可枚举属性组成的数组;
 
classstorage{
constructor(props){
this.props=props||{}
this.source=this.props.source||window.localStorage
this.initRun();
}
initRun(){
/*
*set存储方法
*@param{String}key键
*@param{String}value值,存储的值可能是数组/对象,不能直接存储,需要转换JSON.stringify
*@param{String}expired过期时间,以分钟为单位
*@由@IT·平头哥联盟-首席填坑官∙苏南分享
*/
constreg=newRegExp("__expires__");
letdata=this.source;
letlist=Object.keys(data);
if(list.length>0){
list.map((key,v)=>{
if(!reg.test(key)){
letnow=Date.now();
letexpires=data[`${key}__expires__`]||Date.now+1;
if(now>=expires){
this.remove(key);
};
};
returnkey;
});
};
}
}
总结:
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。