文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

面向对象编程: 原生Javascript实现一个支持过期时间的DAO库

2024-12-03 15:44

关注

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

设计思路


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

正文

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

  1. const BaseStorage = function(preId, timeSign){ 
  2.   // 初始化一些操作 
  3.  
  4. BaseStorage.prototype = { 
  5.   storage: localStorage || window.localStorage, 
  6.   setfunction(key, value, cb, time){ 
  7.      
  8.   }, 
  9.   get: function(key, cb){ 
  10.      
  11.   }, 
  12.   // 删除storage,如果删除成功,返回删除的内容 
  13.   remove: function(key, cb){ 
  14.     
  15.   } 

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

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

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

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

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

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

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

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

set实现

  1. setfunction(key, value, cb, time){ 
  2.      var status = this.status.SUCCESS, 
  3.      key = this.getKey(key); 
  4.      // 设置失效时间,未设置时间默认为一个月 
  5.      try{ 
  6.        time = new Date(time).getTime() || time.getTime(); 
  7.      }catch(e){ 
  8.        time = new Date().getTime() + 1000*60*60*24*31 
  9.      } 
  10.      try{ 
  11.        this.storage.setItem(keytime + this.timeSign + value); 
  12.      }catch(e){ 
  13.        status = this.status.OVERFLOW; 
  14.      } 
  15.      // 操作完成后的回调 
  16.      cb && cb.call(this, status, key, value) 
  17.    } 

get实现

  1. get: function(key, cb){ 
  2.      var status = this.status.SUCCESS, 
  3.      key = this.getKey(key), 
  4.      value = null
  5.      timeSignLen = this.timeSign.length, 
  6.      that = this, 
  7.      index
  8.      time
  9.      result; 
  10.      try{ 
  11.        value = that.storage.getItem(key); 
  12.      }catch(e){ 
  13.        result = { 
  14.          status: that.status.FAILURE, 
  15.          value: null 
  16.        } 
  17.        cb && cb.call(this, result.status, result.value); 
  18.        return result 
  19.      } 
  20.      if(value) { 
  21.        index = value.indexOf(that.timeSign); 
  22.        time = +value.slice(0, index); 
  23.        // 判断是否过期,过期则清除 
  24.        if(time > new Date().getTime() || time == 0){ 
  25.          value = value.slice(index+timeSignLen); 
  26.        }else
  27.          value = null
  28.          status = that.status.TIMEOUT; 
  29.          that.remove(key); 
  30.        } 
  31.      }else
  32.        status = that.status.FAILURE; 
  33.      } 
  34.      result = { 
  35.        status: status, 
  36.        value: value 
  37.      }; 
  38.      cb && cb.call(this, result.status, result.value); 
  39.      return result 
  40.    } 

remove实现

  1. // 删除storage,如果删除成功,返回删除的内容 
  2.    remove: function(key, cb){ 
  3.      var status = this.status.FAILURE, 
  4.      key = this.getKey(key), 
  5.      value = null
  6.      try{ 
  7.        value = this.storage.getItem(key); 
  8.      }catch(e){ 
  9.        // dosomething 
  10.      } 
  11.      if(value){ 
  12.        try{ 
  13.          this.storage.removeItem(key); 
  14.          status = this.status.SUCCESS; 
  15.        }catch(e){ 
  16.          // dosomething 
  17.        } 
  18.      } 
  19.      cb && cb.call(this, status, status > 0 ? null : value.slice(value.indexOf(this.timeSign) + this.timeSign.length)) 
  20.    } 

在api的实现过程中,由于某种误操作很可能导致storage报错,所以建议最好用trycatch包裹,这样可以避免影响后面的逻辑。

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

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

完整源码

  1.  
  2. (function(win){ 
  3.   const BaseStorage = function(preId, timeSign){ 
  4.     this.preId = preId; 
  5.     this.timeSign = timeSign || '|-|'
  6.   } 
  7.   
  8.   BaseStorage.prototype = { 
  9.     status: { 
  10.       SUCCESS: 0, 
  11.       FAILURE: 1, 
  12.       OVERFLOW: 2, 
  13.       TIMEOUT: 3 
  14.     }, 
  15.     storage: localStorage || window.localStorage, 
  16.     getKey: function(key){ 
  17.       return this.preId + key 
  18.     }, 
  19.     setfunction(key, value, cb, time){ 
  20.       var status = this.status.SUCCESS, 
  21.       key = this.getKey(key); 
  22.       // 设置失效时间,未设置时间默认为一个月 
  23.       try{ 
  24.         time = new Date(time).getTime() || time.getTime(); 
  25.       }catch(e){ 
  26.         time = new Date().getTime() + 1000*60*60*24*31 
  27.       } 
  28.       try{ 
  29.         this.storage.setItem(keytime + this.timeSign + value); 
  30.       }catch(e){ 
  31.         status = this.status.OVERFLOW; 
  32.       } 
  33.       cb && cb.call(this, status, key, value) 
  34.     }, 
  35.     get: function(key, cb){ 
  36.       var status = this.status.SUCCESS, 
  37.       key = this.getKey(key), 
  38.       value = null
  39.       timeSignLen = this.timeSign.length, 
  40.       that = this, 
  41.       index
  42.       time
  43.       result; 
  44.       try{ 
  45.         value = that.storage.getItem(key); 
  46.       }catch(e){ 
  47.         result = { 
  48.           status: that.status.FAILURE, 
  49.           value: null 
  50.         } 
  51.         cb && cb.call(this, result.status, result.value); 
  52.         return result 
  53.       } 
  54.       if(value) { 
  55.         index = value.indexOf(that.timeSign); 
  56.         time = +value.slice(0, index); 
  57.         if(time > new Date().getTime() || time == 0){ 
  58.           value = value.slice(index+timeSignLen); 
  59.         }else
  60.           value = null
  61.           status = that.status.TIMEOUT; 
  62.           that.remove(key); 
  63.         } 
  64.       }else
  65.         status = that.status.FAILURE; 
  66.       } 
  67.       result = { 
  68.         status: status, 
  69.         value: value 
  70.       }; 
  71.       cb && cb.call(this, result.status, result.value); 
  72.       return result 
  73.     }, 
  74.     // 删除storage,如果删除成功,返回删除的内容 
  75.     remove: function(key, cb){ 
  76.       var status = this.status.FAILURE, 
  77.       key = this.getKey(key), 
  78.       value = null
  79.       try{ 
  80.         value = this.storage.getItem(key); 
  81.       }catch(e){ 
  82.         // dosomething 
  83.       } 
  84.       if(value){ 
  85.         try{ 
  86.           this.storage.removeItem(key); 
  87.           status = this.status.SUCCESS; 
  88.         }catch(e){ 
  89.           // dosomething 
  90.         } 
  91.       } 
  92.       cb && cb.call(this, status, status > 0 ? null : value.slice(value.indexOf(this.timeSign) + this.timeSign.length)) 
  93.     } 
  94.   } 
  95.   
  96.   win.BS = BaseStorage; 
  97. })(window) 
  98.   

 

 

来源:趣谈前端内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯