給localStorage設(shè)置一個(gè)過(guò)期時(shí)間的方法分享
思考點(diǎn)
在 web 開發(fā)中,我們知道 cookie、session、localStorage都可以保存用戶的數(shù)據(jù),cookie的 domain、path 限制了 cookie 的跨域, 有數(shù)量和大小的限制,可以設(shè)置有效時(shí)間。 session是后臺(tái)在瀏覽器注入一個(gè)設(shè)置了 httponly 的不可讀取的 cookie , session data由后臺(tái)保存在數(shù)據(jù)庫(kù)或者內(nèi)存中,在web中,session 是靠 cookie 作為唯一標(biāo)示來(lái)實(shí)現(xiàn)的,也可以設(shè)置過(guò)期時(shí)間。 localStorage 是 H5 的數(shù)據(jù)存儲(chǔ)辦法, 也是有大小限制的,但是不可以設(shè)置過(guò)期時(shí)間。
從我們接觸前端起,第一個(gè)熟悉的存儲(chǔ)相關(guān)的Cookie或者來(lái)分析我們生活中密切相關(guān)的淘寶、物流、鬧鐘等事物來(lái)說(shuō)起吧,
- Cookie從你設(shè)置的時(shí)候,就會(huì)給個(gè)時(shí)間,不設(shè)置默認(rèn)會(huì)話結(jié)束就過(guò)期;
- 淘寶購(gòu)物 從你下單付款起,就會(huì)給這件貨物設(shè)置一個(gè)收貨期限時(shí)間,過(guò)了這個(gè)時(shí)間自動(dòng)認(rèn)為你收貨(即訂單結(jié)束);
- 鬧鐘 你設(shè)置的提醒時(shí)間,其實(shí)也就是它的過(guò)期時(shí)間;
- 再比如與您每天切身相關(guān)的產(chǎn)品需求,過(guò)完需求,你給出的上線時(shí)間,也就是這個(gè)需求的過(guò)期時(shí)間;
- 再通俗點(diǎn)講,您今年的生日過(guò)完到明年生日之間也是相當(dāng)于設(shè)置了有效期時(shí)間;
以上種種,我們能得出一個(gè)結(jié)論任何一件事、一個(gè)行為動(dòng)作,都有一個(gè)時(shí)間、一個(gè)節(jié)點(diǎn),甚至我們可以黑localStorage,就是一個(gè)完善的API,為什么不能給一個(gè)設(shè)置過(guò)期的機(jī)制,因?yàn)閟essionStorage、Cookie并不能滿足我們實(shí)際的需求。
實(shí)現(xiàn)思路
抱歉,黑localStorage不完善,有點(diǎn)夸張了,綜合上述的總結(jié),問(wèn)題就簡(jiǎn)單了,給localStorage一個(gè)過(guò)期時(shí)間,一切就都so easy ?到底是不是,來(lái)看看具體的實(shí)現(xiàn)吧:
簡(jiǎn)單回顧
//示例一:
localStorage.setItem('test',1234567);
let test = localStorage.getItem('test');
console.log(typeof test, test);
//示例二:
localStorage['name'] = '蘇南';
console.log(localStorage['name']);
/*
輸出:
"1234567" ,'蘇南',
這里要注意,1234567 存進(jìn)去時(shí)是number 取出來(lái)就成string了
*/
重寫 set(存入) 方法:
- 首先有三個(gè)參數(shù) key、value、expired ,分別對(duì)應(yīng) 鍵、值、過(guò)期時(shí)間,
- 過(guò)期時(shí)間的單位可以自由發(fā)揮,小時(shí)、分鐘、天都可以,
- 注意點(diǎn):存儲(chǔ)的值可能是數(shù)組/對(duì)象,不能直接存儲(chǔ),需要轉(zhuǎn)換 JSON.stringify,
- 這個(gè)時(shí)間如何設(shè)置呢?在這個(gè)值存入的時(shí)候在鍵(key)的基礎(chǔ)上擴(kuò)展一個(gè)字段,如:key+'expires',而它的值為當(dāng)前 時(shí)間戳 + expired過(guò)期時(shí)間
具體來(lái)看一下代碼 :
set(key, value, expired) {
/*
* set 存儲(chǔ)方法
* @ param {String} key 鍵
* @ param {String} value 值,
* @ param {String} expired 過(guò)期時(shí)間,以分鐘為單位,非必須
* @ 由@IT·平頭哥聯(lián)盟-首席填坑官∙蘇南 分享
*/
let source = this.source;
source[key] = JSON.stringify(value);
if (expired){
source[`${key}__expires__`] = Date.now() + 1000*60*expired
};
return value;
}
重寫 get(獲取) 方法:
- 獲取數(shù)據(jù)時(shí),先判斷之前存儲(chǔ)的時(shí)間有效期,與當(dāng)前的時(shí)間進(jìn)行對(duì)比;
- 但存儲(chǔ)時(shí)expired為非必須參數(shù),所以默認(rèn)為當(dāng)前時(shí)間+1,即長(zhǎng)期有效;
- 如果存儲(chǔ)時(shí)有設(shè)置過(guò)期時(shí)間,且在獲取的時(shí)候發(fā)現(xiàn)已經(jīng)小于當(dāng)前時(shí)間戳,則執(zhí)行刪除操作,并返回空值;
- 注意點(diǎn):存儲(chǔ)的值可能是數(shù)組/對(duì)象,取出后不能直接返回,需要轉(zhuǎn)換 JSON.parse,
具體來(lái)看一下代碼 :
get(key) {
/*
* get 獲取方法
* @ param {String} key 鍵
* @ param {String} expired 存儲(chǔ)時(shí)為非必須字段,所以有可能取不到,默認(rèn)為 Date.now+1
* @ 由@IT·平頭哥聯(lián)盟-首席填坑官∙蘇南 分享
*/
const source = this.source,
expired = source[`${key}__expires__`]||Date.now+1;
const now = Date.now();
if ( now >= expired ) {
this.remove(key);
return;
}
const value = source[key] ? JSON.parse(source[key]) : source[key];
return value;
}
重寫 remove(刪除) 方法:
刪除操作就簡(jiǎn)單了,;
remove(key) {
const data = this.source,
value = data[key];
delete data[key];
delete data[`${key}__expires__`];
return value;
}
優(yōu)化點(diǎn):
- 記得上次有個(gè)同學(xué),是這么評(píng)論的:「 刪除緩存能放到constructor里面執(zhí)行么,放到get里面 不取就一直在那是不是不太好?」;
- 為什么不用for in而是 for ? for in循環(huán)遍歷對(duì)象的屬性時(shí),原型鏈上的所有屬性都將被訪問(wèn),解決方案:使用hasOwnProperty方法過(guò)濾或Object.keys會(huì)返回自身可枚舉屬性組成的數(shù)組;
class storage {
constructor(props) {
this.props = props || {}
this.source = this.props.source || window.localStorage
this.initRun();
}
initRun(){
/*
* set 存儲(chǔ)方法
* @ param {String} key 鍵
* @ param {String} value 值,存儲(chǔ)的值可能是數(shù)組/對(duì)象,不能直接存儲(chǔ),需要轉(zhuǎn)換 JSON.stringify
* @ param {String} expired 過(guò)期時(shí)間,以分鐘為單位
* @ 由@IT·平頭哥聯(lián)盟-首席填坑官∙蘇南 分享
*/
const reg = new RegExp("__expires__");
let data = this.source;
let list = Object.keys(data);
if(list.length > 0){
list.map((key,v)=>{
if( !reg.test(key )){
let now = Date.now();
let expires = data[`${key}__expires__`]||Date.now+1;
if (now >= expires ) {
this.remove(key);
};
};
return key;
});
};
}
}
總結(jié):
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
JS動(dòng)畫定時(shí)器知識(shí)總結(jié)
這篇文章給大家總結(jié)了關(guān)于JS動(dòng)畫中定時(shí)器的相關(guān)用法以及相關(guān)知識(shí)點(diǎn)總結(jié),有需要的朋友可以參考學(xué)習(xí)下。2018-03-03
JS字符串累加Array不一定比字符串累加快(根據(jù)電腦配置)
言歸正傳:性能差異較大的機(jī)器運(yùn)行結(jié)果會(huì)RT 出現(xiàn)大的差異,為了保險(xiǎn)起見(jiàn)。還是推薦使用Array 來(lái)進(jìn)行字符串拼接操作2012-05-05
用javascript判斷IE版本號(hào)簡(jiǎn)單實(shí)用且向后兼容
項(xiàng)目中需要判斷IE版本號(hào),又因?yàn)?jQuery 2.0 去除了對(duì)瀏覽器版本號(hào)的判斷于是就看到一老外寫的一段代碼,下面與大家分享下2013-09-09
vue2.x的深入學(xué)習(xí)--關(guān)于h函數(shù)的說(shuō)明
下面小編就為大家分享一篇基于h函數(shù)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-08-08
微信小程序如何修改本地緩存key中單個(gè)數(shù)據(jù)的詳解
這篇文章主要介紹了微信小程序如何修改本地緩存key中單個(gè)數(shù)據(jù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
通過(guò)示例演示理解javascript預(yù)解析
這篇文章主要為大家介紹了通過(guò)示例演示理解javascript預(yù)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-03-03
JavaScript之排序函數(shù)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
排序也是在程序中經(jīng)常用到的算法。這篇文章主要介紹了JavaScript之排序函數(shù),有興趣的可以了解一下2017-06-06
javascript應(yīng)用:Iframe自適應(yīng)其加載的內(nèi)容高度
javascript應(yīng)用:Iframe自適應(yīng)其加載的內(nèi)容高度...2007-04-04

