阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 数据缓存与本地存储优化

数据缓存与本地存储优化

作者:陈川 阅读数:32939人阅读 分类: uni-app

数据缓存与本地存储优化

uni-app 开发中,合理利用数据缓存和本地存储能显著提升应用性能。从简单的变量缓存到复杂的数据库操作,不同场景需要选择合适方案。

本地缓存与持久化存储区别

uni-app 提供了两种主要存储方式:

  • 本地缓存:uni.setStorage/uni.getStorage,数据保存在内存中,应用关闭后可能被系统清理
  • 持久化存储:uni.setStorageSync/uni.getStorageSync,数据写入设备存储,长期保留
// 临时缓存示例
uni.setStorage({
  key: 'tempData',
  data: { timestamp: Date.now() },
  success: () => console.log('缓存成功')
})

// 持久化存储示例
try {
  uni.setStorageSync('userToken', 'abc123xyz')
} catch (e) {
  console.error('存储失败', e)
}

缓存策略设计

1. 数据过期机制

为缓存数据添加时间戳,定期验证有效性:

function setCacheWithExpire(key, data, expireHours) {
  const cacheObj = {
    data: data,
    expire: Date.now() + expireHours * 60 * 60 * 1000
  }
  uni.setStorageSync(key, JSON.stringify(cacheObj))
}

function getCacheWithExpire(key) {
  const cacheStr = uni.getStorageSync(key)
  if (!cacheStr) return null
  
  const cacheObj = JSON.parse(cacheStr)
  if (Date.now() > cacheObj.expire) {
    uni.removeStorageSync(key)
    return null
  }
  return cacheObj.data
}

2. 缓存分级策略

  • 一级缓存:内存缓存,使用全局变量
  • 二级缓存:本地存储,使用uni.storage
  • 三级缓存:服务端请求
const memoryCache = {}

function getData(key) {
  // 1. 检查内存缓存
  if (memoryCache[key]) return Promise.resolve(memoryCache[key])
  
  // 2. 检查本地存储
  const localData = getCacheWithExpire(key)
  if (localData) {
    memoryCache[key] = localData
    return Promise.resolve(localData)
  }
  
  // 3. 请求网络
  return fetchDataFromServer(key).then(serverData => {
    memoryCache[key] = serverData
    setCacheWithExpire(key, serverData, 24)
    return serverData
  })
}

存储性能优化

1. 批量操作减少IO

// 低效写法
userList.forEach(user => {
  uni.setStorageSync(`user_${user.id}`, user)
})

// 优化写法
const batchData = {}
userList.forEach(user => {
  batchData[`user_${user.id}`] = user
})
uni.setStorageSync('all_users', batchData)

2. 数据压缩存储

对于大型JSON数据,可以先压缩:

import lzString from 'lz-string'

function setCompressedData(key, data) {
  const compressed = lzString.compressToUTF16(JSON.stringify(data))
  uni.setStorageSync(key, compressed)
}

function getCompressedData(key) {
  const compressed = uni.getStorageSync(key)
  return JSON.parse(lzString.decompressFromUTF16(compressed))
}

特殊场景处理

1. 图片缓存方案

function cacheImage(url) {
  return new Promise((resolve) => {
    const fileName = url.split('/').pop()
    const cacheKey = `img_${fileName}`
    
    // 检查已有缓存
    const cachedPath = uni.getStorageSync(cacheKey)
    if (cachedPath) {
      resolve(cachedPath)
      return
    }
    
    // 下载并缓存
    uni.downloadFile({
      url,
      success: (res) => {
        if (res.statusCode === 200) {
          uni.saveFile({
            tempFilePath: res.tempFilePath,
            success: (saveRes) => {
              uni.setStorageSync(cacheKey, saveRes.savedFilePath)
              resolve(saveRes.savedFilePath)
            }
          })
        }
      }
    })
  })
}

2. 列表分页缓存

const PAGE_SIZE = 10

function cachePageData(listKey, pageNum, data) {
  const pageKey = `${listKey}_page_${pageNum}`
  uni.setStorageSync(pageKey, data)
  
  // 更新列表元信息
  const meta = uni.getStorageSync(`${listKey}_meta`) || {}
  meta.lastUpdate = Date.now()
  meta.totalPages = Math.max(meta.totalPages || 0, pageNum)
  uni.setStorageSync(`${listKey}_meta`, meta)
}

function getCachedPage(listKey, pageNum) {
  const pageKey = `${listKey}_page_${pageNum}`
  return uni.getStorageSync(pageKey)
}

跨平台兼容处理

不同平台存储限制不同:

  • 微信小程序:单个key最大1MB,总上限10MB
  • H5:依赖浏览器实现,通常5MB左右
  • App:基本无限制
function checkStorageSpace() {
  if (uni.getSystemInfoSync().platform === 'android') {
    // Android特殊处理
    return true
  }
  
  try {
    uni.setStorageSync('test_space', new Array(1024 * 1024).join('a'))
    uni.removeStorageSync('test_space')
    return true
  } catch (e) {
    return false
  }
}

数据安全考虑

1. 敏感信息加密

import CryptoJS from 'crypto-js'

const SECRET_KEY = 'your-secret-key-123'

function encryptData(data) {
  return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString()
}

function decryptData(cipherText) {
  const bytes = CryptoJS.AES.decrypt(cipherText, SECRET_KEY)
  return JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
}

2. 自动清理机制

function autoCleanStorage() {
  const now = Date.now()
  const allKeys = uni.getStorageInfoSync().keys
  
  allKeys.forEach(key => {
    if (key.startsWith('cache_')) {
      const data = uni.getStorageSync(key)
      if (data && data.expire && data.expire < now) {
        uni.removeStorageSync(key)
      }
    }
  })
}

// 应用启动时执行
autoCleanStorage()

性能监控与调试

添加存储操作日志:

const storageLogger = {
  log: [],
  maxSize: 100
}

function wrapStorage() {
  const originalSet = uni.setStorageSync
  uni.setStorageSync = function(key, data) {
    storageLogger.log.push({
      type: 'set',
      key,
      size: JSON.stringify(data).length,
      time: Date.now()
    })
    if (storageLogger.log.length > storageLogger.maxSize) {
      storageLogger.log.shift()
    }
    return originalSet.call(uni, key, data)
  }
}

// 初始化包装
wrapStorage()

本地数据库方案

对于复杂数据结构,考虑使用本地数据库:

// 使用indexedDB(H5)
function initDB() {
  return new Promise((resolve) => {
    const request = indexedDB.open('myDatabase', 1)
    
    request.onupgradeneeded = (event) => {
      const db = event.target.result
      if (!db.objectStoreNames.contains('products')) {
        db.createObjectStore('products', { keyPath: 'id' })
      }
    }
    
    request.onsuccess = (event) => {
      resolve(event.target.result)
    }
  })
}

// 使用SQLite(App端)
function initSQLite() {
  plus.sqlite.openDatabase({
    name: 'mydb',
    path: '_doc/mydb.db',
    success: (e) => {
      console.log('数据库打开成功')
    }
  })
}

缓存更新策略

实现智能缓存更新机制:

const cacheStrategies = {
  // 定时更新
  TIMED: (key, getData, interval) => {
    const lastUpdate = uni.getStorageSync(`${key}_lastUpdate`) || 0
    if (Date.now() - lastUpdate > interval) {
      return getData().then(data => {
        uni.setStorageSync(key, data)
        uni.setStorageSync(`${key}_lastUpdate`, Date.now())
        return data
      })
    }
    return Promise.resolve(uni.getStorageSync(key))
  },
  
  // 版本号更新
  VERSIONED: (key, getData, currentVersion) => {
    const cachedVersion = uni.getStorageSync(`${key}_version`)
    if (cachedVersion !== currentVersion) {
      return getData().then(data => {
        uni.setStorageSync(key, data)
        uni.setStorageSync(`${key}_version`, currentVersion)
        return data
      })
    }
    return Promise.resolve(uni.getStorageSync(key))
  }
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌