面向对象编程:NativeJavascript实现一个支持过期时间的DAO库基本思路和模型,我将采用与之前写的不到200行代码如何编写自己的js类库类似的方法。有兴趣的朋友可以学习交流。设计思路我们会在原有的localStorageapi的基础上进行扩展,让它支持过期时间和操作完成后的回调。文末我会给出这个库的完整代码,然后我们一步步实现。Text首先我们来设计库的基本框架:constBaseStorage=function(preId,timeSign){//初始化一些操作}BaseStorage.prototype={storage:localStorage||window.localStorage,set:function(key,value,cb,time){},get:function(key,cb){},//删除存储,如果删除成功,返回删除的内容remove:function(key,cb){}}上面可以看到,我们的storage会有三个核心API,分别是set、get和remove。我们使用localStorage作为基本的库支持。当然你也可以把上面的库换成sessionStorage或者其他的。有了基础骨架,我们就可以实现基础功能的封装。这里我们先给原型添加一个属性,用来列出数据操作中的各种状态。status:{SUCCESS:0,//成功FAILURE:1,//失败OVERFLOW:2,//数据溢出TIMEOUT:3//超时},为了实现过期时间,我们有两种思路,第一种是首先在storage中存入一个过期时间,每次操作都会检查是否过期。但是这种方案意味着必须设置不同过期时间的不同存储键与之对应,会占用额外的库内存,需要维护。也不方便。另一种方法是将过期时间存入keyvalue中,时间和value用标识符分开,每次取值时从value中截取过期时间,然后取出真正的value返回。这种方案不会增加额外的键值对存储,维护起来也比较简单,所以我们采用这种方案。为了区分不同的库对象,我们还可以添加一个key前缀,如下:constBaseLocalStorage=function(preId,timeSign){this.preId=preId;//Keyprefixthis.timeSign=timeSign||'|-|';//过期时间和值的分隔符}基于这个思路,我们接下来就可以实现了。getKey——修改key的方法不影响用户对真实key的影响.SUCCESS,key=this.getKey(key);//设置过期时间,不设置时间默认为一个月尝试{time=newDate(time).getTime()||time.getTime();}catch(e){time=newDate().getTime()+1000*60*60*24*31}试试{这个。storage.setItem(key,time+this.timeSign+value);}catch(e){status=this.status.OVERFLOW;}//回调cb&&cb.call(this,status,key,value)}get实现get:function(key,cb){varstatus=this.status.SUCCESS,key=this.getKey(key),value=null,timeSignLen=this.timeSign.length,that=this,index,time,result;try{value=that.storage.getItem(key);}catch(e){result={status:that.status.FAILURE,value:null}cb&&cb.call(this,result.status,result.value);returnresult}if(value){index=value.indexOf(that.timeSign);time=+value.slice(0,index);//判断是否过期,如果过期则清零if(time>newDate().getTime()||time==0){value=value.slice(index+timeSignLen);}else{值=null,status=that.status.TIMEOUT;that.remove(key);}}else{status=that.status.FAILURE;}result={status:status,value:value};cb&&cb.call(this,result.status,result.value);returnresult}删除实现//删除存储,如果删除成功,返回删除的内容remove:function(key,cb){varstatus=this.status.FAILURE,key=this.getKey(key),value=null;try{value=这。storage.getItem(key);}catch(e){//dosomething}if(value){try{this.storage.removeItem(key);status=this.status.SUCCESS;}catch(e){//dosomething}}cb&&cb.call(this,status,status>0?null:value.slice(value.indexOf(this.timeSign)+this.timeSign.length))}在api执行过程中,由于一些误操作可能导致storage报错,所以建议用trycatch包裹起来,以免影响后面的逻辑接下来我们可以这样使用:leta=newBaseStorage('_','@');a.set('name','123')a.get('name')//{status:0,value:"123"}//设置过期时间a.set('name','123',null,newDate().getTime()+1000*60*60*24*31)//移除a.remove('name')完整源代码/***数据管理器*/(function(win){constBaseStorage=function(preId,timeSign){this.preId=preId;this.timeSign=timeSign||'|-|';}BaseStorage.prototype={status:{SUCCESS:0,FAILURE:1,OVERFLOW:2,TIMEOUT:3},storage:localStorage||window.localStorage,getKey:function(key){returnthis.preId+key},set:function(key,value,cb,time){varstatus=this.status.SUCCESS,key=this.getKey(key);//设置过期时间,如果不设置时间,默认为一个月try{time=newDate(time).getTime()||time.getTime();}catch(e){time=newDate().getTime()+1000*60*60*24*31}try{this.storage.setItem(key,time+this.timeSign+value);}catch(e){status=this.status.OVERFLOW;}cb&&cb.call(this,status,key,value)},get:function(key,cb){varstatus=this.status.SUCCESS,key=this.getKey(key),value=null,timeSignLen=this.timeSign.length,that=this,index,time,result;try{value=that.storage.getItem(key);}catch(e){result={status:that.status.FAILURE,value:null}cb&&cb.call(this,result.status,result.value);returnresult}if(value){index=value.indexOf(that.timeSign);time=+value.slice(0,index);if(time>newDate().getTime()||time==0){value=value.slice(index+timeSignLen);}else{value=null,status=that.status.TIMEOUT;that.remove(key);}}else{status=that.status.FAILURE;}result={status:status,value:value};cb&&cb.call(this,result.status,result.value);returnresult},//删除存储,如果删除成功,返回删除的内容remove:function(key,cb){varstatus=this.status.FAILURE,key=this.getKey(key),value=null;try{value=this.storage.getItem(key);}catch(e){//dosomething}if(value){try{this.storage.removeItem(key);status=this.status.SUCCESS;}catch(e){//dosomething}}cb&&cb.call(this,status,status>0?null:value.slice(value.indexOf(this.timeSign)+this.timeSign.length))}}win.BS=BaseStorage;})(窗口)
