localStorage缓存 接口 配置

localStorage缓存 接口 配置

封装缓存组件 统一管理缓存设置 减少请求 优化逻辑

封装缓存函数

缓存的键和时间也可以放在一起,更好统一管理。

复制代码
// 缓存键前缀
const PREFIX = 'diamond_'

// 缓存时间配置(毫秒)
const CACHE_TIME = {
  SHORT: 5 * 60 * 1000,        // 5分钟
  MEDIUM: 30 * 60 * 1000,      // 30分钟
  LONG: 24 * 60 * 60 * 1000,   // 1天
  WEEK: 7 * 24 * 60 * 60 * 1000 // 1周
}

// 缓存版本号,用于缓存更新
const CACHE_VERSION = '1.0.0'

export const cache = {
  // 设置缓存 默认过期时间30分钟
  set(key, value, expire = CACHE_TIME.MEDIUM) {
    const data = {
      value,
      expire: expire ? Date.now() + expire : null,
      version: CACHE_VERSION
    }
    try {
      localStorage.setItem(PREFIX + key, JSON.stringify(data))
      return true
    } catch (e) {
      // 如果存储失败(存储已满),清理过期缓存后重试
      if (e.name === 'QuotaExceededError') {
        this.clearExpired()
        try {
          localStorage.setItem(PREFIX + key, JSON.stringify(data))
          return true
        } catch (e) {
          console.error('Cache storage failed:', e)
          return false
        }
      }
      return false
    }
  },

  // 获取缓存
  get(key) {
    const data = localStorage.getItem(PREFIX + key)
    if (!data) return null

    try {
      const { value, expire, version } = JSON.parse(data)
      // 检查版本号和过期时间
      if (version !== CACHE_VERSION || (expire && Date.now() > expire)) {
        this.remove(key)
        return null
      }
      return value
    } catch {
      this.remove(key)
      return null
    }
  },

  // 移除缓存
  remove(key) {
    localStorage.removeItem(PREFIX + key)
  },

  // 清除所有缓存
  clear() {
    Object.keys(localStorage).forEach(key => {
      if (key.startsWith(PREFIX)) {
        localStorage.removeItem(key)
      }
    })
  },

  // 清除过期缓存
  clearExpired() {
    Object.keys(localStorage).forEach(key => {
      if (key.startsWith(PREFIX)) {
        try {
          const data = JSON.parse(localStorage.getItem(key))
          if (data.version !== CACHE_VERSION || (data.expire && Date.now() > data.expire)) {
            localStorage.removeItem(key)
          }
        } catch {
          localStorage.removeItem(key)
        }
      }
    })
  },

  // 获取缓存大小(字节)
  size() {
    let size = 0
    Object.keys(localStorage).forEach(key => {
      if (key.startsWith(PREFIX)) {
        size += localStorage.getItem(key).length * 2 // UTF-16 编码每个字符占2字节
      }
    })
    return size
  },

  // 检查缓存是否可用
  isAvailable() {
    try {
      const testKey = PREFIX + 'test'
      localStorage.setItem(testKey, 'test')
      localStorage.removeItem(testKey)
      return true
    } catch {
      return false
    }
  },

  // 获取所有缓存键
  keys() {
    return Object.keys(localStorage)
      .filter(key => key.startsWith(PREFIX))
      .map(key => key.slice(PREFIX.length))
  },

  // 批量设置缓存
  setMany(items, expire = CACHE_TIME.MEDIUM) {
    return items.every(({ key, value }) => this.set(key, value, expire))
  },

  // 批量获取缓存
  getMany(keys) {
    return keys.map(key => ({ key, value: this.get(key) }))
  },

  // 批量删除缓存
  removeMany(keys) {
    keys.forEach(key => this.remove(key))
  }
}

// 缓存键定义
export const CACHE_KEYS = {
  USER_INFO: 'user_info',
  DIAMOND_LIST: 'diamond_list',
  DIAMOND_DETAIL: 'diamond_detail_',
  FILTER_OPTIONS: 'filter_options',
  LANGUAGE: 'language',
  MENU_STATE: 'menu_state',
  THEME: 'theme',
  USER_PREFERENCES: 'user_preferences'
}

// 缓存时间定义
export const CACHE_EXPIRES = {
  USER_INFO: CACHE_TIME.WEEK,
  DIAMOND_LIST: CACHE_TIME.SHORT,
  DIAMOND_DETAIL: CACHE_TIME.MEDIUM,
  FILTER_OPTIONS: CACHE_TIME.LONG,
  LANGUAGE: CACHE_TIME.LONG,
  MENU_STATE: CACHE_TIME.LONG,
  THEME: CACHE_TIME.LONG,
  USER_PREFERENCES: CACHE_TIME.LONG
}

// 定期清理过期缓存(每小时)
if (typeof window !== 'undefined') {
  setInterval(() => {
    cache.clearExpired()
  }, 60 * 60 * 1000)
}

export default cache 

接口缓存

减少每次刷新或跳转进行数据请求,也可以进行二次封装减少代码量

复制代码
import { cache, CACHE_KEYS, CACHE_EXPIRES } from '@/utils/cache'

// 获取钻石列表
export function getDiamondPage(params) {
  // 生成缓存键
  const cacheKey = CACHE_KEYS.DIAMOND_LIST + JSON.stringify(params)
  // 尝试从缓存获取
  const cachedData = cache.get(cacheKey)
  if (cachedData) {
    return Promise.resolve(cachedData)
  }
  // 发起请求
  return request({
    url: '/admin-api/bs/diamond/page',
    method: 'post',
    data: params
  }).then(res => {
    if (res.code === 0) {
      // 设置缓存
      cache.set(cacheKey, res, CACHE_EXPIRES.DIAMOND_LIST)
    }
    return res
  })
}

配置缓存

复制代码
// 获取配置信息
const getCurrentLanguage = () => {
  const cachedLang = cache.get(CACHE_KEYS.LANGUAGE)
  if (cachedLang) return cachedLang
  
  const browserLang = navigator.language.toLowerCase()
  return browserLang.includes('zh') ? 'zh-CN' : 'en-US'
}
// 设置配置信息
cache.set(CACHE_KEYS.LANGUAGE, locale, CACHE_EXPIRES.LANGUAGE)
相关推荐
YOU OU7 小时前
Redis基础常识与命令
数据库·redis·缓存
To_OC7 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
腻害兔7 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
小林ixn9 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
窝子面11 小时前
手搓最简前后端协作-node
javascript·数据库
吳所畏惧11 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
kyriewen12 小时前
我让AI给前端项目做了一次完整的Code Review——它和人类的差距,比我想的大得多
前端·javascript·ai编程
এ慕ོ冬℘゜13 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
sugar__salt14 小时前
Vue3 表单双向绑定与响应式核心 API 技术详解
前端·javascript·vue.js
郝亚军14 小时前
使用Vue 3和Nginx打包和部署Vue.js项目的一般步骤
前端·vue.js·nginx