В этой статье в основном решается проблема, что родной localStorage не может устанавливать время истечения, и реализуется удобная и мощная библиотека localStorage через инкапсуляцию.О некоторых основных идеях и режимах инкапсуляции библиотек я воспользуюсь ранее написаннымКак написать собственную js-библиотеку менее чем за 200 строк кодаПодобным образом заинтересованные друзья могут учиться и общаться.
Идеи дизайна
Мы будем расширять на основе исходного API localStorage, чтобы поддерживать время истечения срока действия и обратный вызов после завершения операции. В конце статьи я приведу код завершения библиотеки, а дальше будем поэтапно его реализовывать.
текст
- Во-первых, давайте спроектируем базовую структуру библиотеки:
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){
}
}
Как вы можете видеть выше, наше хранилище будет иметь три основных API, а именно установить, получить и удалить.Мы используем localStorage в качестве поддержки базовой библиотеки.Конечно, вы также можете заменить указанную выше библиотеку на sessionStorage или другие.
- С помощью базового скелета мы можем реализовать инкапсуляцию основных функций.Здесь мы сначала добавляем атрибут к прототипу, чтобы перечислить различные состояния в операции с данными.
status: {
SUCCESS: 0, // 成功
FAILURE: 1, // 失败
OVERFLOW: 2, // 数据溢出
TIMEOUT: 3 // 超时
},
Для того, чтобы реализовать время истечения, у нас есть две идеи.Первый заключается в том, чтобы сначала хранить время истечения в хранилище и проверять, истекло ли оно для каждой операции, но эта схема означает, что для разных ключей должны быть установлены разные сроки действия. Ей соответствует хранение времени, которое займет дополнительную библиотечную память и неудобно в обслуживании. Другой метод заключается в том, чтобы хранить время истечения в значении ключа, разделять время и значение по идентификатору, перехватывать время истечения из значения каждый раз, когда оно извлекается, а затем извлекать реальное значение и возвращать его.Эта схема не будет добавить Дополнительное хранилище пар ключ-значение относительно просто поддерживать, поэтому мы принимаем эту схему. Чтобы различать разные объекты библиотеки, мы также можем добавить префиксы ключей следующим образом:
const BaseLocalStorage = function(preId, timeSign){
this.preId = preId; // 键前缀
this.timeSign = timeSign || '|-|'; // 过期时间和值的分隔符
}
Основываясь на этой идее, мы можем реализовать следующий шаг.
- Getkee - метод модификации ключа, он не влияет на влияние пользователя на реальный ключ
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, из-за какой-то неправильной работы, очень вероятно, что хранилище сообщит об ошибке, поэтому рекомендуется обернуть его с помощью trycatch, чтобы не влиять на последующую логику.
Далее мы можем использовать его следующим образом:
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)
Вы также можете расширить более мощные функции на основе этого.Если у вас есть идеи получше, добро пожаловать на обмен и обсуждение.
больше рекомендаций
- 9012 научит вас, как использовать gulp4 для разработки шаблонов проекта.
- Как написать собственную библиотеку js менее чем из 200 строк кода)
- Краткое изложение часто используемых js-функций, позволяющих мгновенно повысить эффективность работы (постоянно обновляется)
- Картинка, чтобы научить вас быстро играть в vue-cli3
- 3 минуты, чтобы научить вас использовать нативный js для реализации компонента предварительного просмотра загрузки файлов с мониторингом прогресса
- 3 минуты, чтобы научить вас использовать нативный js для реализации компонента предварительного просмотра загрузки файлов с мониторингом прогресса
- Использование Angular8 и API карты Baidu для разработки «списка туров»
- js реализация базового алгоритма поиска и тест производительности при 1,7 миллионах данных
- Как сделать интерфейсный код в 60 раз быстрее
- "Серия интерфейсных алгоритмов" Дедупликация массива
- Vue advanced advanced series — играйте с vue и vuex с машинописным текстом
- Три года в авангарде, расскажите о 5 самых стоящих книгах, которые стоит прочитать