localStorage過期時間設置的幾種方法
聊到 localStorage 想必熟悉前端的朋友都不會陌生, 我們可以使用它提供的 getItem, setItem, removeItem, clear 這幾個 API 輕松的對存儲在瀏覽器本地的數(shù)據(jù)進行**「讀,寫, 刪」操作, 但是相比于 cookie, localStorage 唯一美中不足的就是「不能設置每一個鍵的過期時間」**。
localStorage 屬性允許我們訪問一個 Document 源(origin)的對象 Storage;存儲的數(shù)據(jù)將保存在瀏覽器會話中。 localStorage 類似 sessionStorage,但其區(qū)別在于:存儲在 localStorage 的數(shù)據(jù)可以長期保留;而當頁面會話結束——也就是說,當頁面被關閉時,存儲在 sessionStorage 的數(shù)據(jù)會被清除 。?
我們還應注意,localStorage 中的鍵值對總是以字符串的形式存儲。
問題描述
在實際的應用場景中, 我們往往需要讓 localStorage 設置的某個 「key」 能在指定時間內(nèi)自動失效, 所以基于這種場景, 我們?nèi)绾稳ソ鉀Q呢?
1. 初級解法
對于剛熟悉前端的朋友, 可能會立馬給出答案:
localStorage.setItem('dooring', '1.0.0')
// 設置一小時的有效期
const expire = 1000 * 60 * 60;
setTimeout(() => {
localStorage.setItem('dooring', '')
}, expire)
當然這種方案能解決一時的問題, 但是如果要設置任意鍵的有效期, 使用這種方案就需要編寫多個定時器, 「維護成本極高, 且不利于工程化復用」。
2. 中級解法
前端工程師在有一定的工作經(jīng)驗之后, 往往會去考慮工程化和復用性的問題, 并對數(shù)據(jù)結構有了一定的了解, 所以可能會有接下來的解法:
- 用**「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份數(shù)據(jù), 并且占用緩存空間
- 如果 EXPIRE_MAP 誤刪除將會導致所有過期時間失效
- 對操作過程缺少更靈活的控制(比如操作狀態(tài), 操作回調(diào)等)
3. 高級解法
為了減少維護成本和空間占用, 并支持一定的靈活控制和容錯能力, 我們又應該怎么做呢?
這里筆者想到了兩種類似的方案:
- 將過期時間存到 key 中, 如 dooring|6000, 每次取值時通過分隔符“|”來將 key 和 expire 取出, 進行判斷
- 將過期時間存到 value 中, 如 1.0.0|6000, 剩下的同1
為了更具有封裝性和可靠性, 我們還可以配置不同狀態(tài)下的回調(diào), 簡單實現(xiàn)如下:
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;
這樣, 我們就實現(xiàn)了每個 key 都有獨立的過期時間, 并且對不同的操作結果可以輕松的進行狀態(tài)管控啦~
4. 骨灰級解法
當然, 骨灰級解法是直接使用 xijs 這個 javascript 工具庫, 因為我已經(jīng)將上述完整實現(xiàn)方案封裝到該庫中了, 我們只需要使用如下的方案, 就能輕松使用具有過期時間的強大的 「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);
// 設置成功后的回調(diào)
store.set('dooring', 'xuxiaoxi', Date.now() + 1000, (status, key, value) => {
console.log('success');
});
同時 xijs 還在持續(xù)擴充更有用的工具函數(shù), 讓業(yè)務開發(fā)更高效. 目前已集成了如下工具函數(shù):
- 「store」 基于 localStorage 上層封裝的支持過期時間設置的緩存庫, 支持操作回調(diào)
- 「uuid」 生成唯一id, 支持設置長度
- 「randomStr」 生成指定個數(shù)的隨機字符串
- 「formatDate」 開箱即用的時間格式化工具
- 「debounce」 防抖函數(shù)
- 「throttle」 節(jié)流函數(shù)
- 「url2obj」 將url字符串轉換為對象
- 「obj2url」 將對象轉換成編碼后的url字符串
- 「isPC」 判斷設備是否為PC類型
github地址: https://github.com/MrXujiang/xijs
文檔地址:h5.dooring.cn/xijs
到此這篇關于localStorage過期時間設置的幾種方法的文章就介紹到這了,更多相關localStorage 過期時間內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
layui實現(xiàn)數(shù)據(jù)表格隱藏列的示例
今天小編就為大家分享一篇layui實現(xiàn)數(shù)據(jù)表格隱藏列的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
js數(shù)組常見操作及數(shù)組與字符串相互轉化實例詳解
這篇文章主要介紹了js數(shù)組常見操作及數(shù)組與字符串相互轉化方法,以實例形式較為詳細的分析并總結了JavaScript數(shù)組的常見使用技巧與轉化方法,需要的朋友可以參考下2015-11-11
在IE和VB中支持png圖片透明效果的實現(xiàn)方法(vb源碼打包)
在IE和VB中支持png圖片透明效果的實現(xiàn)方法(vb源碼打包),需要的朋友可以參考下。2011-04-04
js字符串轉換成數(shù)字與數(shù)字轉換成字符串的實現(xiàn)方法
本篇文章主要是對js字符串轉換成數(shù)字與數(shù)字轉換成字符串的實現(xiàn)方法進行了詳細的介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01

