热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

localstorage设置过期时间_面向对象编程:原生javascript实现一个支持过期时间的DAO库...

本文主要解决原生localStorage无法设置过期时间的问题,并通过封装,来实现一个操作便捷,功能强大的localStorage库&#x

98809abf583b28f3c6a9f5f16da10627.png

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

设计思路

de735ecd3eaf5309f83f7cab30b226cd.png

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

正文

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

 const BaseStorage = 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与之对应,这样会占用额外的库内存,维护起来也不方便。另一种方法就是将过期时间存放到键值中,将时间和值通过标识符分隔,每次取的时候从值中截取过期时间,再将真实的值取出来返回,这种方案不会添加额外的键值对存储,维护起来也相对简单,所以我们采用这种方案。 为了区分不同的库对象,我们还可以添加键前缀,如下:

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

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

  • getKey——修饰key的方法,不影响用户对真实key的影响

getKey: function(key){
     return this.preId + key
   },

  • set实现

set: function(key, value, cb, time){
     var status = this.status.SUCCESS,
     key = this.getKey(key);
     // 设置失效时间,未设置时间默认为一个月
     try{
       time = new Date(time).getTime() || time.getTime();
     }catch(e){
       time = new Date().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){
     var status = 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);
       return result
     }
     if(value) {
       index = value.indexOf(that.timeSign);
       time = +value.slice(0, index);
       // 判断是否过期,过期则清除
       if(time > new Date().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);
     return result
   }

  • remove实现

// 删除storage,如果删除成功,返回删除的内容
   remove: function(key, cb){
     var status = 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包裹,这样可以避免影响后面的逻辑。

接下来我们可以这么使用:

let a = new BaseStorage('_', '@');
a.set('name', '123')
a.get('name') // {status: 0, value: "123"}
// 设置失效时间
a.set('name', '123', null, new Date().getTime() + 1000*60*60*24*31)
// 移除
a.remove('name')

完整源码

/**
 * 数据管理器
 */
(function(win){
  const BaseStorage = 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){
      return this.preId + key
    },
    set: function(key, value, cb, time){
      var status = this.status.SUCCESS,
      key = this.getKey(key);
      // 设置失效时间,未设置时间默认为一个月
      try{
        time = new Date(time).getTime() || time.getTime();
      }catch(e){
        time = new Date().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){
      var status = 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);
        return result
      }
      if(value) {
        index = value.indexOf(that.timeSign);
        time = +value.slice(0, index);
        if(time > new Date().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);
      return result
    },
    // 删除storage,如果删除成功,返回删除的内容
    remove: function(key, cb){
      var status = 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)
 

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

3945e62a094a748a76e35c039191f3df.gif

点个在看 你最好看

319b380d7c587ffaaea81f9b4b40a4bf.png



推荐阅读
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文是一篇翻译文章,介绍了async/await的用法和特点。async关键字被放置在函数前面,意味着该函数总是返回一个promise。文章还提到了可以显式返回一个promise的方法。该特性使得async/await更易于理解和使用。本文还提到了一些可能的错误,并希望读者能够指正。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
author-avatar
孟海滨_554
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有