localStorage過期時間設置的幾種方法
聊到 localStorage 想必熟悉前端的朋友都不會陌生, 我們可以使用它提供的 getItem, setItem, removeItem, clear 這幾個 API 輕松的對存儲在瀏覽器本地的數據進行**「讀,寫, 刪」操作, 但是相比於 cookie, localStorage 唯一美中不足的就是「不能設置每一個鍵的過期時間」**。
localStorage 屬性允許我們訪問一個 Document 源(origin)的對象 Storage;存儲的數據將保存在瀏覽器會話中。 localStorage 類似 sessionStorage,但其區別在於:存儲在 localStorage 的數據可以長期保留;而當頁面會話結束——也就是說,當頁面被關閉時,存儲在 sessionStorage 的數據會被清除 。
我們還應註意,localStorage 中的鍵值對總是以字符串的形式存儲。
問題描述
在實際的應用場景中, 我們往往需要讓 localStorage 設置的某個 「key」 能在指定時間內自動失效, 所以基於這種場景, 我們如何去解決呢?
1. 初級解法
對於剛熟悉前端的朋友, 可能會立馬給出答案:
localStorage.setItem('dooring', '1.0.0') // 設置一小時的有效期 const expire = 1000 * 60 * 60; setTimeout(() => { localStorage.setItem('dooring', '') }, expire)
當然這種方案能解決一時的問題, 但是如果要設置任意鍵的有效期, 使用這種方案就需要編寫多個定時器, 「維護成本極高, 且不利於工程化復用」。
2. 中級解法
前端工程師在有一定的工作經驗之後, 往往會去考慮工程化和復用性的問題, 並對數據結構有瞭一定的瞭解, 所以可能會有接下來的解法:
- 用**「localStorage」**存一份{key(鍵): expire(過期時間)}的映射表
- 重寫**「localStorage API」**, 對方法進行二次封裝
類似的代碼如下:
const store = { // 存儲過期時間映射 setExpireMap: (key, expire) => { const expireMap = localStorage.getItem('EXPIRE_MAP') || "{}" localStorage.setItem( 'EXPIRE_MAP', JSON.stringify({ ...JSON.parse(expireMap), key: expire })) }, setItem: (key, value, expire) => { store.setExpireMap(key, expire) localStorage.setItem(key, value) }, getItem: (key) => { // 在取值之前先判斷是否過期 const expireMap = JSON.parse( localStorage.getItem('EXPIRE_MAP') || "{}" ) if(expireMap[key] && expireMap[key] < Date.now()) { return localStorage.getItem(key) }else { localStorage.removeItem(key) return null } } // ... }
眨眼一看這個方案確實解決瞭復用性的問題, 並且不同團隊都可以使用這個方案, 但仍然有一些缺點:
- 對 store 操作時需要維護2份數據, 並且占用緩存空間
- 如果 EXPIRE_MAP 誤刪除將會導致所有過期時間失效
- 對操作過程缺少更靈活的控制(比如操作狀態, 操作回調等)
3. 高級解法
為瞭減少維護成本和空間占用, 並支持一定的靈活控制和容錯能力, 我們又應該怎麼做呢?
這裡筆者想到瞭兩種類似的方案:
- 將過期時間存到 key 中, 如 dooring|6000, 每次取值時通過分隔符“|”來將 key 和 expire 取出, 進行判斷
- 將過期時間存到 value 中, 如 1.0.0|6000, 剩下的同1
為瞭更具有封裝性和可靠性, 我們還可以配置不同狀態下的回調, 簡單實現如下:
const store = { preId: 'xi-', timeSign: '|-door-|', status: { SUCCESS: 0, FAILURE: 1, OVERFLOW: 2, TIMEOUT: 3, }, storage: localStorage || window.localStorage, getKey: function (key: string) { return this.preId + key; }, set: function ( key: string, value: string | number, time?: Date & number, cb?: (status: number, key: string, value: string | number) => void, ) { let _status = this.status.SUCCESS, _key = this.getKey(key), _time; // 設置失效時間,未設置時間默認為一個月 try { _time = time ? new Date(time).getTime() || time.getTime() : new Date().getTime() + 1000 * 60 * 60 * 24 * 31; } catch (e) { _time = new Date().getTime() + 1000 * 60 * 60 * 24 * 31; } try { this.storage.setItem(_key, _time + this.timeSign + value); } catch (e) { _status = this.status.OVERFLOW; } cb && cb.call(this, _status, _key, value); }, get: function ( key: string, cb?: (status: number, value: string | number | null) => void, ) { let status = this.status.SUCCESS, _key = this.getKey(key), value = null, timeSignLen = this.timeSign.length, that = this, index, time, result; try { value = that.storage.getItem(_key); } catch (e) { result = { status: that.status.FAILURE, value: null, }; cb && cb.call(this, result.status, result.value); return result; } if (value) { index = value.indexOf(that.timeSign); time = +value.slice(0, index); if (time > new Date().getTime() || time == 0) { value = value.slice(index + timeSignLen); } else { (value = null), (status = that.status.TIMEOUT); that.remove(_key); } } else { status = that.status.FAILURE; } result = { status: status, value: value, }; cb && cb.call(this, result.status, result.value); return result; }, // ... }; export default store;
這樣, 我們就實現瞭每個 key 都有獨立的過期時間, 並且對不同的操作結果可以輕松的進行狀態管控啦~
4. 骨灰級解法
當然, 骨灰級解法是直接使用 xijs 這個 javascript 工具庫, 因為我已經將上述完整實現方案封裝到該庫中瞭, 我們隻需要使用如下的方案, 就能輕松使用具有過期時間的強大的 「localStorage」 方法啦 :
// 先安裝 yarn add xijs import { store } from 'xijs'; // 設置帶有過期時間的key store.set('name', 'dooring', Date.now() + 1000); console.log(store.get('name')); setTimeout(() => { console.log(store.get('name')); }, 1000); // 設置成功後的回調 store.set('dooring', 'xuxiaoxi', Date.now() + 1000, (status, key, value) => { console.log('success'); });
同時 xijs 還在持續擴充更有用的工具函數, 讓業務開發更高效. 目前已集成瞭如下工具函數:
- 「store」 基於 localStorage 上層封裝的支持過期時間設置的緩存庫, 支持操作回調
- 「uuid」 生成唯一id, 支持設置長度
- 「randomStr」 生成指定個數的隨機字符串
- 「formatDate」 開箱即用的時間格式化工具
- 「debounce」 防抖函數
- 「throttle」 節流函數
- 「url2obj」 將url字符串轉換為對象
- 「obj2url」 將對象轉換成編碼後的url字符串
- 「isPC」 判斷設備是否為PC類型
github地址: https://github.com/MrXujiang/xijs
文檔地址:h5.dooring.cn/xijs
到此這篇關於localStorage過期時間設置的幾種方法的文章就介紹到這瞭,更多相關localStorage 過期時間內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Vue的緩存方法示例詳解
- localStorage設置有效期和過期時間的簡單方法
- vue項目如何監聽localStorage或sessionStorage的變化
- 一文教你如何實現localStorage的過期機制
- 前端項目中監聽localStorage的變化