成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官: 如何讓localStorage支持過期時(shí)間設(shè)置?

開發(fā) 前端
localStorage 屬性允許我們訪問一個(gè) Document 源(origin)的對象 Storage;存儲的數(shù)據(jù)將保存在瀏覽器會話中。

[[440024]]

聊到 localStorage 想必熟悉前端的朋友都不會陌生, 我們可以使用它提供的 getItem, setItem, removeItem, clear 這幾個(gè) API 輕松的對存儲在瀏覽器本地的數(shù)據(jù)進(jìn)行讀,寫, 刪操作, 但是相比于 cookie, localStorage 唯一美中不足的就是不能設(shè)置每一個(gè)鍵的過期時(shí)間。

localStorage 屬性允許我們訪問一個(gè) Document 源(origin)的對象 Storage;存儲的數(shù)據(jù)將保存在瀏覽器會話中。localStorage 類似 sessionStorage,但其區(qū)別在于:存儲在 localStorage 的數(shù)據(jù)可以長期保留;而當(dāng)頁面會話結(jié)束——也就是說,當(dāng)頁面被關(guān)閉時(shí),存儲在 sessionStorage 的數(shù)據(jù)會被清除 。

我們還應(yīng)注意,localStorage 中的鍵值對總是以字符串的形式存儲。

問題描述

在實(shí)際的應(yīng)用場景中, 我們往往需要讓 localStorage 設(shè)置的某個(gè) key 能在指定時(shí)間內(nèi)自動(dòng)失效, 所以基于這種場景, 我們?nèi)绾稳ソ鉀Q呢?

1. 初級解法

對于剛熟悉前端的朋友, 可能會立馬給出答案:

  1. localStorage.setItem('dooring''1.0.0'
  2. // 設(shè)置一小時(shí)的有效期 
  3. const expire = 1000 * 60 * 60; 
  4. setTimeout(() => { 
  5.   localStorage.setItem('dooring'''
  6. }, expire) 

當(dāng)然這種方案能解決一時(shí)的問題, 但是如果要設(shè)置任意鍵的有效期, 使用這種方案就需要編寫多個(gè)定時(shí)器, 維護(hù)成本極高, 且不利于工程化復(fù)用。

2. 中級解法

前端工程師在有一定的工作經(jīng)驗(yàn)之后, 往往會去考慮工程化和復(fù)用性的問題, 并對數(shù)據(jù)結(jié)構(gòu)有了一定的了解, 所以可能會有接下來的解法:

  1. 用localStorage存一份{key(鍵): expire(過期時(shí)間)}的映射表
  2. 重寫localStorage API, 對方法進(jìn)行二次封裝

類似的代碼如下:

  1. const store = { 
  2.   // 存儲過期時(shí)間映射 
  3.   setExpireMap: (key, expire) => { 
  4.     const expireMap = localStorage.getItem('EXPIRE_MAP') || "{}" 
  5.     localStorage.setItem( 
  6.       'EXPIRE_MAP',  
  7.       JSON.stringify({ 
  8.       ...JSON.parse(expireMap), 
  9.       key: expire 
  10.     })) 
  11.   }, 
  12.   setItem: (key, value, expire) => { 
  13.     store.setExpireMap(key, expire) 
  14.     localStorage.setItem(key, value) 
  15.   }, 
  16.   getItem: (key) => { 
  17.     // 在取值之前先判斷是否過期 
  18.     const expireMap = JSON.parse( 
  19.       localStorage.getItem('EXPIRE_MAP') || "{}" 
  20.     ) 
  21.     if(expireMap[key] && expireMap[key] < Date.now()) { 
  22.       return localStorage.getItem(key
  23.     }else { 
  24.       localStorage.removeItem(key
  25.       return null 
  26.     } 
  27.   } 
  28.   // ... 

眨眼一看這個(gè)方案確實(shí)解決了復(fù)用性的問題, 并且不同團(tuán)隊(duì)都可以使用這個(gè)方案, 但仍然有一些缺點(diǎn):

  • 對 store 操作時(shí)需要維護(hù)2份數(shù)據(jù), 并且占用緩存空間
  • 如果 EXPIRE_MAP 誤刪除將會導(dǎo)致所有過期時(shí)間失效
  • 對操作過程缺少更靈活的控制(比如操作狀態(tài), 操作回調(diào)等)

3. 高級解法

為了減少維護(hù)成本和空間占用, 并支持一定的靈活控制和容錯(cuò)能力, 我們又應(yīng)該怎么做呢?

這里筆者想到了兩種類似的方案:

  1. 將過期時(shí)間存到 key 中, 如 dooring|6000, 每次取值時(shí)通過分隔符“|”來將 key 和 expire 取出, 進(jìn)行判斷
  2. 將過期時(shí)間存到 value 中, 如 1.0.0|6000, 剩下的同1

為了更具有封裝性和可靠性, 我們還可以配置不同狀態(tài)下的回調(diào), 簡單實(shí)現(xiàn)如下:

  1. const store = { 
  2.   preId: 'xi-'
  3.   timeSign: '|-door-|'
  4.   status: { 
  5.     SUCCESS: 0, 
  6.     FAILURE: 1, 
  7.     OVERFLOW: 2, 
  8.     TIMEOUT: 3, 
  9.   }, 
  10.   storage: localStorage || window.localStorage, 
  11.   getKey: function (key: string) { 
  12.     return this.preId + key
  13.   }, 
  14.   setfunction ( 
  15.     key: string, 
  16.     value: string | number, 
  17.     time?: Date & number, 
  18.     cb?: (status: number, key: string, value: string | number) => void, 
  19.   ) { 
  20.     let _status = this.status.SUCCESS, 
  21.       _key = this.getKey(key), 
  22.       _time; 
  23.     // 設(shè)置失效時(shí)間,未設(shè)置時(shí)間默認(rèn)為一個(gè)月 
  24.     try { 
  25.       _time = time 
  26.         ? new Date(time).getTime() || time.getTime() 
  27.         : new Date().getTime() + 1000 * 60 * 60 * 24 * 31; 
  28.     } catch (e) { 
  29.       _time = new Date().getTime() + 1000 * 60 * 60 * 24 * 31; 
  30.     } 
  31.     try { 
  32.       this.storage.setItem(_key, _time + this.timeSign + value); 
  33.     } catch (e) { 
  34.       _status = this.status.OVERFLOW; 
  35.     } 
  36.     cb && cb.call(this, _status, _key, value); 
  37.   }, 
  38.   get: function ( 
  39.     key: string, 
  40.     cb?: (status: number, value: string | number | null) => void, 
  41.   ) { 
  42.     let status = this.status.SUCCESS, 
  43.       _key = this.getKey(key), 
  44.       value = null
  45.       timeSignLen = this.timeSign.length, 
  46.       that = this, 
  47.       index
  48.       time
  49.       result; 
  50.     try { 
  51.       value = that.storage.getItem(_key); 
  52.     } catch (e) { 
  53.       result = { 
  54.         status: that.status.FAILURE, 
  55.         value: null
  56.       }; 
  57.       cb && cb.call(this, result.status, result.value); 
  58.       return result; 
  59.     } 
  60.     if (value) { 
  61.       index = value.indexOf(that.timeSign); 
  62.       time = +value.slice(0, index); 
  63.       if (time > new Date().getTime() || time == 0) { 
  64.         value = value.slice(index + timeSignLen); 
  65.       } else { 
  66.         (value = null), (status = that.status.TIMEOUT); 
  67.         that.remove(_key); 
  68.       } 
  69.     } else { 
  70.       status = that.status.FAILURE; 
  71.     } 
  72.     result = { 
  73.       status: status, 
  74.       value: value, 
  75.     }; 
  76.     cb && cb.call(this, result.status, result.value); 
  77.     return result; 
  78.   }, 
  79.   // ... 
  80. }; 
  81.  
  82. export default store; 

這樣, 我們就實(shí)現(xiàn)了每個(gè) key 都有獨(dú)立的過期時(shí)間, 并且對不同的操作結(jié)果可以輕松的進(jìn)行狀態(tài)管控啦~

4. 骨灰級解法

當(dāng)然, 骨灰級解法是直接使用 xijs 這個(gè) javascript 工具庫, 因?yàn)槲乙呀?jīng)將上述完整實(shí)現(xiàn)方案封裝到該庫中了, 我們只需要使用如下的方案, 就能輕松使用具有過期時(shí)間的強(qiáng)大的 localStorage 方法啦 :

  1. //  先安裝 yarn add xijs 
  2. import { store } from 'xijs'
  3. // 設(shè)置帶有過期時(shí)間的key 
  4. store.set('name''dooring'Date.now() + 1000); 
  5. console.log(store.get('name')); 
  6. setTimeout(() => { 
  7.   console.log(store.get('name')); 
  8. }, 1000); 
  9.  
  10. // 設(shè)置成功后的回調(diào) 
  11. store.set('dooring''xuxiaoxi'Date.now() + 1000, (status, key, value) => { 
  12.   console.log('success'); 
  13. }); 

同時(shí) xijs 還在持續(xù)擴(kuò)充更有用的工具函數(shù), 讓業(yè)務(wù)開發(fā)更高效. 目前已集成了如下工具函數(shù):

  • store 基于 localStorage 上層封裝的支持過期時(shí)間設(shè)置的緩存庫, 支持操作回調(diào)
  • uuid 生成唯一id, 支持設(shè)置長度
  • randomStr 生成指定個(gè)數(shù)的隨機(jī)字符串
  • formatDate 開箱即用的時(shí)間格式化工具
  • debounce 防抖函數(shù)
  • throttle 節(jié)流函數(shù)
  • url2obj 將url字符串轉(zhuǎn)換為對象
  • obj2url 將對象轉(zhuǎn)換成編碼后的url字符串
  • isPC 判斷設(shè)備是否為PC類型

本文轉(zhuǎn)載自微信公眾號「趣談前端」

【編輯推薦】

 

責(zé)任編輯:姜華 來源: 趣談前端
相關(guān)推薦

2024-05-09 10:33:14

JS計(jì)算容量

2015-08-13 10:29:12

面試面試官

2024-04-09 08:39:16

本地緩存開發(fā)線程安全

2023-02-16 08:10:40

死鎖線程

2024-04-08 10:35:59

JS代碼容量

2024-12-26 10:19:16

2010-08-12 16:28:35

面試官

2024-04-03 00:00:00

Redis集群代碼

2024-09-11 22:51:19

線程通訊Object

2021-07-06 07:08:18

管控數(shù)據(jù)數(shù)倉

2025-03-17 00:00:00

2023-11-20 10:09:59

2024-02-20 14:10:55

系統(tǒng)緩存冗余

2024-03-18 14:06:00

停機(jī)Spring服務(wù)器

2021-03-01 18:42:02

緩存LRU算法

2019-07-23 09:30:17

HTTP 2.0HTTP協(xié)議傳輸

2021-02-06 09:21:17

MySQL索引面試

2019-04-29 14:59:41

Tomcat系統(tǒng)架構(gòu)

2024-04-23 14:09:59

JavaScript開發(fā)

2023-09-01 15:27:31

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美在线一区二区三区 | 免费在线一区二区 | 一级大黄色片 | 三级视频久久 | 久久精品91 | 一区二区三区免费 | 久久新视频 | 日本人和亚洲人zjzjhd | 99精品免费视频 | 精品中文在线 | 久久精品一区 | 欧美日韩精品 | 日本三级黄视频 | 一区二区三区视频在线观看 | 免费观看一区二区三区毛片 | 麻豆视频在线免费看 | 天天干夜夜操 | 成人超碰 | 欧美专区在线视频 | 欧美一区二区三区 | 91在线视频国产 | 日韩中文电影 | 亚洲视频欧美视频 | 91激情电影 | 天堂网中文字幕在线观看 | 午夜成人在线视频 | 91精品国产91久久久久久最新 | 四虎影院新地址 | 91精品久久久 | 国产一区二区a | 午夜视频精品 | 日屁网站| 久久伊人一区二区 | www.日本在线| 国产一级成人 | 精品91久久 | 亚洲一区二区中文字幕在线观看 | 婷婷综合网 | 国产欧美在线观看 | 精品国产一区二区国模嫣然 | 中文字幕一区二区三区四区 |