高级前端dom【Q556】如何封装一个支持过期时间的 localStorage

如何封装一个支持过期时间的 localStorage

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 571

Author 回答者: heretic-G

function initLocalStorage() {
  localStorage.setItem = function (key, value, time = 1000) {
    const expiresTime = Date.now() + time * 1000;
    const payload = {
      __data: value,
      __expiresTime: expiresTime,
    };
    Storage.prototype.setItem.call(localStorage, key, JSON.stringify(payload));
  };
  localStorage.getItem = function (key) {
    const value = Storage.prototype.getItem.call(localStorage, key);
    if (typeof value === "string") {
      const jsonVal = JSON.parse(value);
      if (jsonVal.__expiresTime) {
        if (jsonVal.__expiresTime >= Date.now()) {
          return JSON.stringify(jsonVal.__data);
        } else {
          return null;
        }
      }
    }
    return value;
  };
}
initLocalStorage();

想了下 只能去改api 去封装一层 不过存在一个问题就是别人在使用的时候 也需要遵循这个规则 没想到别的办法

Author 回答者: shfshanyue

设置如下数据结构,当用户存储数据时,存储至 __value 字段。并将过期时间存储至 __expires 字段。

{
  __value, __expires;
}

而当每次获取数据时,判断当前时间是否已超过 __expires 过期时间,如果超过,则返回 undefined,并删除该数据。

Author 回答者: justorez

@heretic-G 简单改了下,支持 localStorage 默认的用法,只有传入时间过期才生效:

(function () {
  localStorage.setItem = function (key, value, time = Infinity) {
    const payload = Number.isFinite(time)
      ? {
          __data: value,
          __expiresTime: Date.now() + time,
        }
      : value;
    Storage.prototype.setItem.call(localStorage, key, JSON.stringify(payload));
  };
  localStorage.getItem = function (key) {
    const value = Storage.prototype.getItem.call(localStorage, key);
    try {
      const jsonVal = JSON.parse(value);
      if (jsonVal.__expiresTime) {
        return jsonVal.__expiresTime >= Date.now()
          ? JSON.stringify(jsonVal.__data)
          : void 0;
      }
      return value;
    } catch (error) {
      return value;
    }
  };
})();