关于javascript:支持过期时间和按模块管理的localStorage

前言

在前端开发中,localStorage的应用是十分多的,然而原生的localStorage有些性能是没有的,比方:

  1. 无奈设置每一个键的过期工夫
  2. 无奈按模块治理localStorage

一、如何应用

先来看看如何应用的,再看实现办法:

1、初始化时传入moduleName

let storage = new Storage('user'); // 设置了模块名为user
storage.setItem('name', '张三', 60 * 60 * 24); // 过期工夫1天
storage.setItem('age', 18);

storage.clear(); // 清空所有localStorage
storage.clear('user'); // 清空模块名user的localStorage

2、初始化时不传入moduleName

let storage = new Storage();
storage.setItem('name', '张三', 60 * 60 * 24, 'user'); // 过期工夫1天、模块名为user
storage.setItem('name', 'mac', 'system'); // 模块名为system

storage.getItem('name', 'system'); // 获取模块system下的name
storage.clear('system'); // 清空模块名system的localStorage

获取时如果过期了,则会主动清空数据,并返回状态

二、实现代码

class Storage {
  constructor(moduleName) {
    this.moduleName = moduleName;
    this.storage = localStorage || window.localStorage;
    this.status = {
      SUCCESS: 0,
      FAILURE: 1, // 失败
      OVERFLOW: 2, // 超出限度,localstorage最大反对5M的数据(每个浏览器各自又有些不同)
      TIMEOUT: 3 // 过期
    };
  }

  setItem(key, value) {
    let expire, moduleName, args = Array.prototype.slice.call(arguments, 2);
    if (args.length > 0) { // 解决参数程序
      if (typeof args[0] == 'number') {
        [expire, moduleName] = args;
      } else {
        [moduleName, expire] = args;
      }
    }

    key = this.normalizeKey(key, moduleName);
    let status = this.status.SUCCESS, data = value;

    if (!expire && ['[object Object]', '[object Array]'].indexOf(Object.prototype.toString.call(value)) > -1) { // 没有设置过期工夫 + 是对象或数组
      data = JSON.stringify(value);
    } else if (expire) {
      data = JSON.stringify({
        value,
        _expireTime_: new Date().getTime() + expire * 1000
      });
    }

    try {
      this.storage.setItem(key, data);
    } catch(e) {
      status = this.status.OVERFLOW;
    }

    return status;
  }

  getItem(key, moduleName) {
    let status = this.status.SUCCESS, data = null;
    key = this.normalizeKey(key, moduleName);

    try {
      data = this.storage.getItem(key);
    } catch(e) {
      status = this.status.FAILURE;
    }

    try {
      data = JSON.parse(data);
    } catch (error) {}

    if (data && data.value && data._expireTime_) { // 设置了生效工夫
      if (new Date().getTime() > data._expireTime_) { // 生效
        data = null;
        status = this.status.TIMEOUT;
        this.storage.removeItem(key)
      } else {
        data = data.value;
      }
    }
    return {
      status,
      value: data
    };
  }

  clear(moduleName) {
    if (moduleName) {
      const keys = Object.keys(this.storage);
      keys.forEach(key => {
        if (key.indexOf(moduleName + '/') === 0) {
          this.storage.removeItem(key);
        }
      })
    } else {
      this.storage.clear();
    }
  }

  normalizeKey(key, moduleName) {
    let ModuleName = moduleName || this.moduleName; // 独自设置就用独自设置的,否则用初始化时候传入的
    if (typeof key !== 'string') {
      console.warn(`${key} used as a key, but it is not a string.`);
      key = String(key);
    }
    return `${ModuleName ? ModuleName + '/' : ''}${key}`;
  }
}

以上就是我本人封装的localStorage啦,心愿能够帮到有须要的人,如果能够的话,麻烦点个赞或者珍藏下呦~

结尾

我是周小羊,一个前端萌新,写文章是为了记录本人日常工作遇到的问题和学习的内容,晋升本人,如果您感觉本文对你有用的话,麻烦点个赞激励一下哟~

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理