基于 localStorage 实现一个具有过期时间的 DAO 库

简介: 本文主要解决原生localStorage无法设置过期时间的问题,并通过封装,来实现一个操作便捷,功能强大的localStorage库,关于库封装的一些基本思路和模式,我将采用之前写的如何用不到200行代码写一款属于自己的js类库中类似的方法,感兴趣的朋友可以学习,交流。

本文主要解决原生localStorage无法设置过期时间的问题,并通过封装,来实现一个操作便捷,功能强大的localStorage库,关于库封装的一些基本思路和模式,我将采用之前写的如何用不到200行代码写一款属于自己的js类库中类似的方法,感兴趣的朋友可以学习,交流。


设计思路


我们将基于localStorage原始api进行扩展,让其支持失效时间,操作完成后的回调。在文章的最后,我将给出库的完成代码,接下来我们就一步步实现吧。


正文


  1. 首先,我们来设计库的基本框架:


constBaseStorage=function(preId, timeSign){
// 初始化一些操作 }
BaseStorage.prototype= {
storage: localStorage||window.localStorage,
set: function(key, value, cb, time){
   },
get: function(key, cb){
   },
// 删除storage,如果删除成功,返回删除的内容remove: function(key, cb){
   }
 }

如上可以发现,我们的storage会有三个核心api,分别为set,get,remove,我们使用localStorage作为基础库支持,当然你也可以将上面的库换成sessionStorage或者其他。


  1. 有了基本骨架,我们就可以实现基本功能的封装,这里我们先在原型中加一个属性,来列出数据操作中的各个状态。


status: {
SUCCESS: 0, // 成功FAILURE: 1, // 失败OVERFLOW: 2, // 数据溢出TIMEOUT: 3// 超时},

为了实现过期时间,我们有两种思路,第一种是先将一个过期时间存到storage中,每次操作都检查一遍是否过期,但是这种方案意味着对不同的键就要设置不同的过期时间的storage与之对应,这样会占用额外的库内存,维护起来也不方便。另一种方法就是将过期时间存放到键值中,将时间和值通过标识符分隔,每次取的时候从值中截取过期时间,再将真实的值取出来返回,这种方案不会添加额外的键值对存储,维护起来也相对简单,所以我们采用这种方案。 为了区分不同的库对象,我们还可以添加键前缀,如下:


constBaseLocalStorage=function(preId, timeSign){
this.preId=preId; // 键前缀this.timeSign=timeSign||'|-|';  // 过期时间和值的分隔符 }

基于这个思想,我们就可以接下来的实现了。


  • getKey——修饰key的方法,不影响用户对真实key的影响
getKey: function(key){
returnthis.preId+key   },
  • set实现
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实现
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实现
// 删除storage,如果删除成功,返回删除的内容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))
   }

在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    },
// 删除storage,如果删除成功,返回删除的内容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;
})(window)

大家也可以基于此扩展更强大的功能,如果有更好的想法,欢迎交流,探讨。

目录
相关文章
|
缓存 NoSQL Java
Java实现redis缓存效果变量过期
Java实现redis缓存效果变量过期
98 0
|
1月前
|
缓存 NoSQL 算法
解决Redis缓存雪崩问题的有效方法
解决Redis缓存雪崩问题的有效方法
42 1
|
3月前
|
缓存 前端开发 CDN
静态资源缓存过期时间的设置
【8月更文挑战第18天】静态资源缓存过期时间的设置
80 1
|
3月前
|
JSON JavaScript 前端开发
Vue项目使用Cookie,以Json格式存入与读取Cookie,设置过期时间以及删除操作
这篇文章介绍了在Vue项目中如何使用JavaScript操作Cookie,包括设置、读取、设置过期时间以及删除Cookie的方法。
278 0
|
5月前
|
缓存 JavaScript
请问如何在 keep-alive 组件中设置缓存的最大数量和过期时间
请问如何在 keep-alive 组件中设置缓存的最大数量和过期时间
|
6月前
|
NoSQL Java Redis
springboot整合redis过期key监听实现订单过期操作
springboot整合redis过期key监听实现订单过期操作
334 0
|
11月前
|
存储 程序员 PHP
修改session的过期(生存)时间
以下我以php为例,万变不离其宗,希望对大家都有用吧。 session与cookie: 了解过两者的众所都知道,有些信息保存到cookie,有些出于安全问题就不能直接存到浏览器,这就要用到session了。然而对于浏览器,一般都是默认20-30分钟自动销毁或者关闭浏览器就会销毁。这显示是很头疼的事情,比如我们要实现用户登陆功能,关闭浏览器就要重新登陆,这搞什么鬼?所以我们要去试图改变它们。网上众说纷纭,你可以选择去修改默认配置文件,如php为例,修改php.ini的函数。但是染念却不喜欢修改修改默认,也在网上看到某些程序员是没有权限修改的,所以我们需要做到如何不修改默认文件达到这样的功能。
63 0
|
存储 JavaScript
本地存储(localStorage)如何设置过期时间?
在我们使用cookie的时候是可以设置有效期的,但是localStorage本身是没有该机制的,只能人为的手动删除,否则会一直存放在浏览器当中,可不可以跟cookie一样设置一个有效期。如果一直存放在浏览器又感觉有点浪费,那我们可以把localStorage进行二次封装实现该方案。
478 0
本地存储(localStorage)如何设置过期时间?
|
存储 JavaScript
typescript封装LocalStorage并支持过期时间
在存储的时候设置一个过期时间,并且存储的数据进行格式化方便统一校验,在读取的时候获取当前时间进行判断是否过期,如果过期进行删除即可。
189 0
typescript封装LocalStorage并支持过期时间
|
存储 设计模式 数据库
Yii2如何设置session的过期时间?底层原理是什么?
Yii2如何设置session的过期时间?底层原理是什么?
372 0