范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

如何让localStorage支持过期时间设置

  前言
  最近在项目开发中,遇见了大家都常会遇见的问题,让本地存储支持过期时间的设置。那相信学习前端的童鞋们都知道,我们经常是会用的 cookie 、localStorage 、sessionStorage ,它们三个都是可以用来存放数据的。这里我们就不细讲它们之间的区别,主要讲当我们设置localStorage 的时候,怎么来给它设置一个过期时间了?下来我们就开始今天的主题。封装
  根据一般的业务需求,我们需要支持`新增,修改,删除`,按照初步设想,开始编写我们代码。可跳过中间部分,直接查看最后的完整版代码示例。(TS目前还有不太熟练的地方,有什么地方有问题欢迎指出)// 定义类 class NStorage {   storage: Storage;   constructor(name?: string) {     this.storage = window[name as keyof typeof window] || window.localStorage   }   /**    * @description 存储方法    * @param {String} key 键名    * @param {any} value 值    * @param {number} [expires] 可选,默认0,永久    */   set(key: string, value: any, expires: number = 0) {     const storeValue = {       value,       startTime: new Date().getTime(),       __expires__: expires     }     this.storage.setItem(key, JSON.stringify(storeValue))   }   /**    * @description 获取方法    * @param {String} key 键名    * @returns {any} 值    */   get(key: string) {     try {       const storeItem = this.storage.getItem(key) || "{}"       const storeValue = JSON.parse(storeItem)       const time = new Date().getTime()       // 如果是永久,则直接返回       if (storeValue?.__expires__ === 0) return storeValue       // 判断当前时间是否过期       if (storeValue?.startTime && (time - storeValue?.startTime >= storeValue?.__expires__)) {         this.remove(key);         return null;       }       return storeValue.value     } catch (error) {       return null     }   }   /**    * @description 删除方法    * @param {String} key 删除键名    */   remove(key: string) {     key && this.storage.removeItem(key);   }   /**    * @description 清除所有本地存储    */   clear() {     this.storage.clear();   } }
  下面是本地测试:const store = new NStorage()  store.set("name", "小红", { expires: 10 })  let count = 0 const time = setInterval(() => {   const name = store.get("name")   console.log(name)   count += 1    if (count > 10) {     clearInterval(time)   } }, 1000)
  在控制台可以看见打印的 小红 ,3秒后localStorage 里面的值就会被删除。功能我们是实现啦,是不是就可以皆大欢喜了?有没有bug?有没有可以优化的问题了?那当然是有的了:
  1. 设置的过期时间,表示的是秒?分?小时?
  2. 如果多次设置同一个值,那么依据现在逻辑,每次都会重新计算时间,但是我可能只是更新值,时间不需要重新计算了?优化
  定义出选项类型// 定义支持时间类型,依次:年、月、日、时、分、秒 type TUnitType = "Y" | "M" | "D" | "h" | "m" | "s" // 定义可选参类型 interface IExtraOptions {   expires?: number;   unit?: TUnitType,   reset?: boolean }  // 设置默认初始值 const EXTRA_OPTIONS: IExtraOptions = {   expires: 0, // 默认永久   unit: "s", // 默认秒   reset: false // 是否重置时间 } // 根据单位和传入时间,计算出毫秒级时间 function calcTime(time: number, unit: TUnitType = "s") {   let newTime = 0   switch (unit) {     case "Y":       newTime = time * 365 * 24 * 60 * 60 * 1000       break;     case "M":       // 注意⚠️:月份这里偷懒,直接使用每月30天计算       newTime = time * 30 * 24 * 60 * 60 * 1000       break;     case "D":       newTime = time * 24 * 60 * 60 * 1000       break;     case "h":       newTime = time * 60 * 60 * 1000       break;     case "m":       newTime = time * 60 * 1000       break;     case "s":       newTime = time * 1000       break;     default:       newTime = time       break;   }   return newTime }   **修改 set、get 方法**    /**    * @description 存储方法    * @param {String} key 键名    * @param {any} value 值    * @param {number} [options] 可选    * @param {Number} [options.expires] 默认0,永久    * @param {String} [options.unit] 默认"s",秒    * @param {Boolean} [options.reset] 默认false,不重置    */   set(key: string, value: any, options?: IExtraOptions) {   const isExist = this.hasKey(key)   const extra = Object.assign(EXTRA_OPTIONS, options)   if (isExist) {     // 如果存在,判断是否是需要重新设置值     const sValue = this.get(key, true)     sValue.value = value     sValue.__expires__ = calcTime(extra.expires || sValue.__expires__, extra.unit || sValue.__unit__)     if (extra.reset) {       // 存在且重新设置时间       sValue.startTime = new Date().getTime()       this._set(key, sValue)     } else {       // 如果已经存在,且不重新计算时间,则直接修改值后存储       this._set(key, sValue)     }   } else {     const storeValue = {       value,       startTime: new Date().getTime(),       __expires__: calcTime(extra.expires as number, extra.unit),       __unit__: extra.unit     };     this._set(key, storeValue)   } }   /**    * @description set内部方法    * @param {String} key 键名    * @param {any} value 值    */   private _set(key: string, value: any) {     this.storage.setItem(key, JSON.stringify(value));   }   /**    * @description 获取方法    * @param {String} key 键名    * @param {Boolean} [isMerge] 可选,是否获取处理后的对象    * @returns {any} 值    */   get(key: string, isMerge: boolean = false) {     try {       // 不存在直接返回 null       if (!key) return null       const storeItem = this.storage.getItem(key) || "{}"       const storeValue = JSON.parse(storeItem)       const time = new Date().getTime()       // 如果是永久,则直接返回       if (storeValue?.__expires__ === 0) return isMerge ? storeValue : storeValue.value;       // 判断当前时间是否过期,过期则删除当前存储值       if (storeValue?.startTime && (time - storeValue?.startTime >= storeValue?.__expires__)) {         this.remove(key);         return null;       }       return isMerge ? storeValue : storeValue.value;     } catch (error) {       return null     }   }   /**    * @description 是否存在    * @param {String} key 键    * @returns {Boolean} true|false    */   hasKey(key: string) {     if (!key) return false     const value = this.get(key)     return value ? true : false   }优化后使用介绍const store = new NStorage() // 普通设置,不过期 store.set("name", "小红") // 设置过期时间5秒 store.set("name", "小红", { expires: 5 }) // 设置过期时间5分钟,其他更换单位即可 store.set("name", "小红", { expires: 5, unit: "m" }) // 重新计算有效时长(就相当于在设置的时刻起,再往后延长之前的设置时间) store.set("name", "小红", { reset: true })  // 获取值 store.get("name")  // 删除值 store.remove("name")  // 删除所有值 store.clear()  // 当前存储值中是否存在 store.hasKey("name")完整版代码// 定义支持时间类型,依次:年、月、日、时、分、秒 type TUnitType = "Y" | "M" | "D" | "h" | "m" | "s" // 定义可选参类型 interface IExtraOptions {   expires?: number;   unit?: TUnitType,   reset?: boolean }  // 设置默认初始值 const EXTRA_OPTIONS: IExtraOptions = {   expires: 0, // 默认永久   unit: "s", // 默认秒   reset: false // 是否重置时间 } // 根据单位和传入时间,计算出毫秒级时间 function calcTime(time: number, unit: TUnitType = "s") {   let newTime = 0   switch (unit) {     case "Y":       newTime = time * 365 * 24 * 60 * 60 * 1000       break;     case "M":       // 月份这里偷懒,直接使用每月30天计算       newTime = time * 30 * 24 * 60 * 60 * 1000       break;     case "D":       newTime = time * 24 * 60 * 60 * 1000       break;     case "h":       newTime = time * 60 * 60 * 1000       break;     case "m":       newTime = time * 60 * 1000       break;     case "s":       newTime = time * 1000       break;     default:       newTime = time       break;   }   return newTime }  class NStorage {   storage: Storage;   constructor(name?: string) {     this.storage = window[name as keyof typeof window] || window.localStorage   }   /**    * @description 存储方法    * @param {String} key 键名    * @param {any} value 值    * @param {number} [options] 可选    * @param {Number} [options.expires] 默认0,永久    * @param {String} [options.unit] 默认"s",秒    * @param {Boolean} [options.reset] 默认false,不重置    */   set(key: string, value: any, options?: IExtraOptions) {     const isExist = this.hasKey(key)     const extra = Object.assign(EXTRA_OPTIONS, options)     if (isExist) {       // 如果存在,判断是否是需要重新设置值       const sValue = this.get(key, true)       sValue.value = value       sValue.__expires__ = calcTime(extra.expires || sValue.__expires__, extra.unit || sValue.__unit__)       if (extra.reset) {         // 存在且重新设置时间         sValue.startTime = new Date().getTime()         this._set(key, sValue)       } else {         // 如果已经存在,且不重新计算时间,则直接修改值后存储         this._set(key, sValue)       }     } else {       const storeValue = {         value,         startTime: new Date().getTime(),         __expires__: calcTime(extra.expires as number, extra.unit),         __unit__: extra.unit       };       this._set(key, storeValue)     }   }   /**    * @description set内部方法    * @param {String} key 键名    * @param {any} value 值    */   private _set(key: string, value: any) {     this.storage.setItem(key, JSON.stringify(value));   }   /**    * @description 获取方法    * @param {String} key 键名    * @param {Boolean} [isMerge] 可选,是否获取处理后的对象    * @returns {any} 值    */   get(key: string, isMerge: boolean = false) {     try {       // 不存在直接返回 null       if (!key) return null       const storeItem = this.storage.getItem(key) || "{}"       const storeValue = JSON.parse(storeItem)       const time = new Date().getTime()       // 如果是永久,则直接返回       if (storeValue?.__expires__ === 0) return isMerge ? storeValue : storeValue.value;       // 判断当前时间是否过期,过期则删除当前存储值       if (storeValue?.startTime && (time - storeValue?.startTime >= storeValue?.__expires__)) {         this.remove(key);         return null;       }       return isMerge ? storeValue : storeValue.value;     } catch (error) {       return null     }   }   /**    * @description 删除方法    * @param {String} key 删除键名    */   remove(key: string) {     key && this.storage.removeItem(key);   }   /**    * @description 清除所有本地存储    */   clear() {     this.storage.clear();   }   /**    * @description 是否存在    * @param {String} key 键    * @returns {Boolean} true|false    */   hasKey(key: string) {     if (!key) return false     const value = this.get(key)     return value ? true : false   } }最后
  里面的逻辑也可根据需求自己添加修改,代码测试我也可能存在未测到的地方,如果有问题欢迎各位大大指出!

多事之秋,2022保险大事盘点,还有更大的大事么?2022年还剩最后10天这是多事之秋的一年系列大事深刻地影响着保险业01大批保险公司评级不达标据银保监会公布2022年第三季度181家纳入评审的公司15家得C,9家得DCD合计共有日本央行货币政策突变图为行人走在日本东京站丸之内出口附近的马路上。孙佳林摄(新华社发)12月20日,日本央行在为期两天的货币政策会议上,决定调整部分收益率曲线控制(YCC)政策,将长期利率波动幅度从原12月FOMC会议报告市场预期主要央行加息周期何时见顶?内容摘要美联储加息50bp,将联邦基金利率目标区间上调至4。254。5,同幅度上调超额准备金利率至4。4隔夜逆回购利率至4。3。对于2024年,有7名委员认为应降息100bp至44永兴联通创新打造智慧社区助力社会治理数字化红网时刻新闻12月22日讯(通讯员何杨)日前,由永兴联通打造的智慧社区平台正式亮相于永兴金穗家园小区,通过数字赋能实现社区治理全域化网格管理精细化,智慧社区让服务居民更有温度,更有新消费观察快递春节不打烊,物流企业纷纷推出年货消费保障计划封面新闻记者雷强随着春节临近,采购年货成了不少消费者的头等大事。春节不打烊已成为近年快递业的标配,目前已有多家快递企业联合电商平台开始为年货春运做准备。天猫和菜鸟12月21日宣布,隔夜美股大指数均涨超1汽车板块小鹏涨近1112月21日美东时间周三,耐克与联邦快递两家大型公司的财报点燃了企业盈利状况可能好于预期的希望。市场仍在评估美联储政策前景与美国经济衰退风险,截止收盘,道指收盘上涨526。74点,年度家电总结消费篇尽管2022年开启于冬奥会的欢快气氛中,但冬奥会结束后,全球便迎来俄乌冲突黑天鹅,原本已经处于回落区间的原材料价格再度飙升,欧美地区的通胀水平进一步拉高,美联储紧接着启动加息,将全2023年就业重点活动有哪些?请查收央视网消息中央经济工作会议强调,对于我们这么大的经济体而言,保持经济平稳运行至关重要。要着力稳增长稳就业稳物价,保持经济运行在合理区间。该如何稳就业?13月,人力资源社会保障部组织什么是富硒农产品?缺硒人群如何选择富硒农产品?随着生活习惯和饮食习惯的改变,如今越来越多的人成为亚健康人群,主要表现有怕冷怕热易于感冒骨质疏松睡眠紊乱等。造成亚健康状态的原因有很多,总结起来就是内因和外因,内因主要是受情绪影响山东深化预算绩效管理改革2019年以来,山东省深化财政预算绩效管理改革,进行事前事中事后全过程绩效评价。通过对项目预算进行成本分析测算和控制,强化监督考核,试点地区把钱花在刀刃上,有效化解了财政收支矛盾,冯杰争分夺秒履行与自己的十年之约工人日报中工网记者邹明强通讯员王嵩松李晴14年前,河南农村小伙冯杰,一脸的稚气入职江汉石油工程公司。形单影只的青葱少年,望向一台台正在驶入基地的压裂车组,他却暗自下定决心,未来一定
书评七界传说三间七界最强的天之都,反而是最先毁灭的一界在七界传说中,共分为三间七界,域之三界天之三界和人界。其中人间是根本,其他六界都是被开辟出来的异域空间。天之都没有顶尖高手,但整体实力却是七界中最强的。无他,寿命太长也!在浩瀚天地苗苗郭碧婷同时生二胎,为何一个被祝福,一个被喷生娃机器?这几期的跑男,都没有郑恺,节目组而已宣称,郑凯陪老婆苗苗在坐月子,春风吹又生了!看到苗苗郑凯在网上记录的月子视频,确实很日常很幸福了!都说生男孩会鼻子大,看苗苗确实是鼻子看起来大了数字公共卫生的进展与应用点击蓝字关注我们引用本文韩雨廷,吕筠,余灿清,等。数字公共卫生的进展与应用J。中华流行病学杂志,2022,43(6)791797。DOI10。3760cma。j。cn1123382山水同程清凉三日游丨穿越ampampquot最美公路ampampquot,打卡山水画廊线路特色1最美公路线,十渡山水线一进一出,沿途美景无边2游高峡平湖,碧波荡漾,一幅天然山水画卷3住在森林里,海拔高,群山绕,坐看云海夜观星空4踏浪拒马河,夏天亲水正当时线路行程第一快乐家族5人现状曝光当初最不起眼的,如今资源最大咖快乐大本营,天天好心情!2021年9月25日,谁也没想到,这一期将会成为快乐家族在快本的绝唱,不久,快乐大本营便被打上了停播的标签。而失去快本后,以节目为主体建立的快乐家族也不得不企业招聘,进过方舱的不要?阳过的不要?这种偏见不要有近日,个别新冠康复者在求职时遇到让人费解的歧视性指标,引发网友热议。今年春天,湖北十堰的陈峰(化名)来到上海,在方舱医院工作时期被确诊为阳性,6月1日治愈出院。本该迎接新生活的他却同样是嫁豪门,把董卿王艳和郭晶晶等放一起看,差距一目了然混迹娱乐圈男明星似乎没有一个固定的落脚点,有人演而优则导,像徐峥黄磊有人演而优则综艺,像孙红雷沙溢而女明星的目标相对单纯而一致,那就是有朝一日嫁入豪门,但一入豪门深似海,豪门难进更落跑实锤!苏贞昌大笔一挥,批准林智坚请辞新竹市长林智坚(中)。(图片来源台湾中时新闻网)中国台湾网7月7日讯民进党籍新竹市长林智坚近日身陷论文门风暴,外界好奇,他原定7月8日请辞新竹市长投入桃园市长的时间表是否会有所改变?据台媒执业药师考试拿证变简单?官方通知多地可单独下调合格标准日前,国家药监局执业药师资格认证中心发布执业药师考试相关消息,给这些地区考生带来政策性好消息!文末附通知原文新增多地执行单独划线2019年人社部曾印发关于在三区三州等深度贫困地区单赵伟油价跌猪价涨,低通胀能否延续中新经纬7月7日电题油价跌猪价涨,低通胀能否延续作者赵伟国金证券首席经济学家猪价回升或推动CPI通胀升温生猪供给量上升猪价大幅下跌,一度拖累CPI(消费者价格指数)食品项。伴随着能南京女大学生被害案一审宣判1人死刑2人死缓2020年,21岁南京女大学生李某月在云南被杀害,此事备受关注。2022年7月7日,云南省西双版纳傣族自治州中级人民法院一审公开宣判被告人洪峤张晨光曹泽青故意杀人,被告人洪峤祁文强