предисловие
Фактический адрес боевой доставки проекта:
Шаблоны проектирования | Базовая инкапсуляция запросов
Борьба с проектами | Реализация уровня бизнес-процессинга
В предыдущих блогах мы использовалифабрика,играет рольрежим для инкапсуляции собственного метода кэширования. В этой статье мы оптимизируем детали метода кэширования для повышения качества проекта.
Пакет хранения
базовый пакет
class Storage {
constructor(props = {}) { // 根据类型跟缓存时间,初始化缓存方法
const { type = 'local', time = 5000, cacheSize = 2.5 } = props
this.type = type
this.time = time
this.cacheSize = cacheSize * 1024 * 1024
this.storageType = {
local: 'localStorage',
session: 'sessionStorage',
cookie: 'cookie',
indexDb: 'indexDb',
normal: 'normal'
}
}
baseSetItem(key, value) { // 接管原生新增方法
return {
local() { window[this.storageType[this.type]].setItem(key, value) },
session() { window[this.storageType[this.type]].setItem(key, value) },
cookie() { },
indexDb() { },
normal() {
if (!window.baseStorage) {
window.baseStorage = {}
} else {
window.baseStorage[key] = value
}
},
}
}
baseRemoveItem(key) { // 接管原生删除方法
return {
local() { window[this.storageType[this.type]].removeItem(key) },
session() { window[this.storageType[this.type]].removeItem(key) },
cookie() { },
indexDb() { },
normal() {
delete window.baseStorage[key]
},
}
}
setItem(key, value) { // 代理原生缓存方法,添加缓存时间
this.baseSetItem(key, JSON.stringify({
value,
time: new Date().getTime()
}))[this.type].apply(this)
}
getItem(key) { // 代理原生获取缓存方法,根据缓存时间,判断数据是否过期
try {
const { time, value } = JSON.parse(window[this.storageType[this.type]].getItem(key));
const now = new Date().getTime()
if (now > time + this.time) {
this.baseRemoveItem(key, reValue)[this.type].apply(this)
return null
} else {
return value
}
} catch (e) {
return null
}
}
}
const local = new Storage({ type: 'local', time: 30000 }) // 初始化localStorage,添加5分钟缓存时效
const session = new Storage({ type: 'session', time: 30000 }) // 初始化sessionStorage,添加5分钟缓存时效
local.setItem(1, 2)
local.getItem(1)
Как и выше, мы передаем собственный метод кэширования черезфабрика,играет роль,СтратегияПосле завершения инкапсуляции методы чтения всех кешей унифицируются, что облегчает вызов на стороне бизнеса (из-за нехватки места здесь нет соответствующего метода, добавленного в cookie и indexDb, который будет дополнен в демо позже)
суждение простого типа
Это очень просто, нужно отфильтровать вообще бессмысленное, такое как null и undefined (Вы можете сделать свое собственное суждение, основанное на бизнесе, некоторые проекты могут иметь смысл), а кеш операций — небезопасная операция, можно обернуть try/catch,Безопасность прежде всего.
setItem(key, value) { // 代理原生缓存方法,添加缓存时间
if (!value) return
try {
this.baseSetItem(key, JSON.stringify({
value,
time: new Date().getTime()
}))[this.type]()
} catch (error) {
console.log(error)
}
}
Получить размер используемого локального кэша
В localStorage общий браузер поддерживает размер 5M.В браузерах с разными ядрами localStorage будет другим, поэтому мы должны обращать внимание на то, чтобы не превышать максимальный размер кеша при использовании кеша.
getCacheSize() {
let storage = window[this.storageType[this.type]];
if (storage !== "") {
let size = 0;
for (let item in storage) {
if (storage.hasOwnProperty(item)) {
size += storage.getItem(item).length;
}
}
return size
}
return false
}
Вышеупомянутый метод является распространенным методом получения размера локального кеша.Когда мы инициализируем хранилище, мы можем установить максимальный размер, который нам удобен для выполнения других операций при превышении максимального размера. Вообще говоря, чтобы избежать работы в других частях проекта и совместимости с большинством браузеров, наша настройка кеша по умолчанию составляет 2,5 МБ.
constructor(props = {}) { // 根据类型跟缓存时间,初始化缓存方法
const { type = 'local', time = 5000, cacheSize = 2.5 } = props
this.type = type
this.time = time
this.cacheSize = cacheSize * 1024 * 1024
this.storageType = {
local: 'localStorage',
session: 'sessionStorage',
cookie: 'cookie',
indexDb: 'indexDb',
normal: 'normal'
}
this.initEstimate() // 初始化已用缓存
}
initEstimate() {
if (navigator && navigator.storage) {
navigator.storage.estimate().then(estimate => {
this.usage = estimate.usage
this.quota = estimate.quota
console.log(this.usage, this.quota)
});
} else {
this.usage = this.getCacheSize(this.type)
}
console.log(this.usage)
}
Один из вышеперечисленных методов для инициализации используемого размера кэшаnavigator.storage.estimateметод, этот метод поддерживает только некоторые браузеры и может использоваться только вhttpsИспользуемый в соответствии с протоколом, это веб-API для получения пространства использования локального кеша и максимального значения. Для конкретного использования см.StorageEstimate. Эта статья пока не делает дополнительного расширения этого метода, и позже он будет улучшен в демоверсии.
Обработка ситуаций, когда превышен максимальный размер кэша
Когда наши данные необходимо кэшировать, а объем данных превышает заданный максимальный размер кэша, есть два решения:
- данные согласнопервым прибыл, первым обслуженпринцип, удалите первые сохраненные данные кеша, пока размер кеша не сможет хранить новые данные
- Выберите в соответствии с количеством вызовов кеша и отдайте приоритетНизкая частота использования и увеличенное время храненияданные удаляются до тех пор, пока размер кэша не станет достаточно большим для хранения новых данных в
В качестве демонстрации мы возьмем первый метод грубой силы для решения этой проблемы.
getCacheSort() { // 获取本地缓存数据且按照时间排序
let storage = window[this.storageType[this.type]];
if (storage !== "") {
let storageList = [];
for (let item in storage) {
if (storage.hasOwnProperty(item)) {
storageList.push({
key: item,
value: storage.getItem(item)
})
}
}
return storageList.sort((a, b) => {
return JSON.parse(a.value).time - JSON.parse(b.value).time
})
}
return false
}
judgeMemory(value) { // 判断缓存大小,当存入数据缓存大小 + 已使用缓存大小超过预设最大值的时候,循环删除数据,指导能够存入新的数据为止
if (this.getSize(value) + this.usage > this.cacheSize) {
const storageList = this.getCacheSort()
for (let { key, value } of storageList) {
if (this.getSize(value) + this.usage < this.cacheSize) break
this.usage = this.usage - this.getSize(value)
this.baseRemoveItem(key)[this.type].apply(this)
}
} else {
this.usage = this.getSize(value) + this.usage
}
}
setItem(key, value) { // 代理原生缓存方法,添加缓存时间
try {
if (!value) return
const reValue = JSON.stringify({
value,
time: new Date().getTime()
})
this.judgeMemory(reValue) // 存入数据之前先调用内存判断方法
this.baseSetItem(key, reValue)[this.type].apply(this)
} catch (error) {
console.log(error)
}
}
Поскольку метка времени также добавляется к содержимому, которое мы храним, это потребует дополнительного места в памяти.Если фактический проект не соответствует лимиту, его можно игнорировать. Вторая схема также требует расчета количества вызовов и дополнительно занимает больше места в кэше, схему можно выбрать в реальном проекте. Конечно, в целом немногие проекты потребуют столь детальных операций.
Вышеупомянутое упакованное хранилище не учитывает производительность.Некоторые студенты хотят напрямую представить проект для использования.Если есть проблема с производительностью, вы можете оптимизировать ее.
конец
Полный демонстрационный адрес:Боевая демонстрация проекта, Если вам это нравится, вы можете пометить его. В дальнейшем мы будем постепенно расширять этот проект в соответствии с введением сообщения в блоге шаблона проектирования.
Если у вас есть какие-либо вопросы или идеи по содержанию статьи и примеров, вы можете добавить WeChat Cookieboty для общения.