咱們將基於localStorage原始api進行擴展,讓其支持失效時間,操做完成後的回調。在文章的最後,我將給出庫的完成代碼,接下來咱們就一步步實現吧。前端
const BaseStorage = function(preId, timeSign){
// 初始化一些操做
}
BaseStorage.prototype = {
storage: localStorage || window.localStorage,
set: function(key, value, cb, time){
},
get: function(key, cb){
},
// 刪除storage,若是刪除成功,返回刪除的內容
remove: function(key, cb){
}
}
複製代碼
如上能夠發現,咱們的storage會有三個核心api,分別爲set,get,remove,咱們使用localStorage做爲基礎庫支持,固然你也能夠將上面的庫換成sessionStorage或者其餘。vue
status: {
SUCCESS: 0, // 成功
FAILURE: 1, // 失敗
OVERFLOW: 2, // 數據溢出
TIMEOUT: 3 // 超時
},
複製代碼
爲了實現過時時間,咱們有兩種思路,第一種是先將一個過時時間存到storage中,每次操做都檢查一遍是否過時,可是這種方案意味着對不一樣的鍵就要設置不一樣的過時時間的storage與之對應,這樣會佔用額外的庫內存,維護起來也不方便。另外一種方法就是將過時時間存放到鍵值中,將時間和值經過標識符分隔,每次取的時候從值中截取過時時間,再將真實的值取出來返回,這種方案不會添加額外的鍵值對存儲,維護起來也相對簡單,因此咱們採用這種方案。 爲了區分不一樣的庫對象,咱們還能夠添加鍵前綴,以下:算法
const BaseLocalStorage = function(preId, timeSign){
this.preId = preId; // 鍵前綴
this.timeSign = timeSign || '|-|'; // 過時時間和值的分隔符
}
複製代碼
基於這個思想,咱們就能夠接下來的實現了。vuex
getKey: function(key){
return this.preId + key
},
複製代碼
set: function(key, value, cb, time){
var status = this.status.SUCCESS,
key = this.getKey(key);
// 設置失效時間,未設置時間默認爲一個月
try{
time = new Date(time).getTime() || time.getTime();
}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, cb){
var 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
}
複製代碼
// 刪除storage,若是刪除成功,返回刪除的內容
remove: function(key, cb){
var status = this.status.FAILURE,
key = this.getKey(key),
value = null;
try{
value = this.storage.getItem(key);
}catch(e){
// dosomething
}
if(value){
try{
this.storage.removeItem(key);
status = this.status.SUCCESS;
}catch(e){
// dosomething
}
}
cb && cb.call(this, status, status > 0 ? null : value.slice(value.indexOf(this.timeSign) + this.timeSign.length))
}
複製代碼
在api的實現過程當中,因爲某種誤操做極可能致使storage報錯,因此建議最好用trycatch包裹,這樣能夠避免影響後面的邏輯。vue-cli
接下來咱們能夠這麼使用:typescript
let a = new BaseStorage('_', '@');
a.set('name', '123')
a.get('name') // {status: 0, value: "123"}
// 設置失效時間
a.set('name', '123', null, new Date().getTime() + 1000*60*60*24*31)
// 移除
a.remove('name')
複製代碼
/** * 數據管理器 */
(function(win){
const BaseStorage = function(preId, timeSign){
this.preId = preId;
this.timeSign = timeSign || '|-|';
}
BaseStorage.prototype = {
status: {
SUCCESS: 0,
FAILURE: 1,
OVERFLOW: 2,
TIMEOUT: 3
},
storage: localStorage || window.localStorage,
getKey: function(key){
return this.preId + key
},
set: function(key, value, cb, time){
var status = this.status.SUCCESS,
key = this.getKey(key);
// 設置失效時間,未設置時間默認爲一個月
try{
time = new Date(time).getTime() || time.getTime();
}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, cb){
var 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
},
// 刪除storage,若是刪除成功,返回刪除的內容
remove: function(key, cb){
var status = this.status.FAILURE,
key = this.getKey(key),
value = null;
try{
value = this.storage.getItem(key);
}catch(e){
// dosomething
}
if(value){
try{
this.storage.removeItem(key);
status = this.status.SUCCESS;
}catch(e){
// dosomething
}
}
cb && cb.call(this, status, status > 0 ? null : value.slice(value.indexOf(this.timeSign) + this.timeSign.length))
}
}
win.BS = BaseStorage;
})(window)
複製代碼
你們也能夠基於此擴展更強大的功能,若是有更好的想法,歡迎交流,探討。gulp
歡迎關注下方公衆號,獲取更多前端知識精粹和學習社羣: api
回覆學習路徑,將獲取筆者多年從業經驗的前端學習路徑的思惟導圖;數組
交流微信羣:微信