前端做接口缓存并统一管理

1,165 阅读2分钟

前端做接口缓存并统一管理

因为最近做的产品看的数据是历史数据,也就是说请求多次参数一样返回结果都一样,为了切换页面时loading少一点,做了缓存。开始的方案是将缓存写在当前页面,发现代码量太多,不好一次性清空缓存,于是想到了统一管理

需求:接口缓存,可一次清除缓存,可缓存可不缓存,代码量小。

思路:

  • 存数据、统一管理:定义一个数组cacheData
  • 一次清空:cacheData = []
  • 可缓存可不缓存: 定义一个参数(isCache)来判断
  • 考虑到前端都做了请求封装: 可以在封装的方法前加个中间层来判断是否要取缓存中的数据(requestCacheWrapper)

实现:

request.ts

interface CacheDataItem {
  apiDataString: string
  data: any
}

// 缓存数据存在这里
let cacheData:Array<CacheDataItem> = []
// 缓存数据上限 总览页和活动页不包括表格排序时大概缓存60个接口数据
const cacheDataMaxLength:number = 100

// 清空缓存
export const wipeCache = () => {
  cacheData = []
}

// 获取缓存数据index
const getCacheIndex = (apiDataString, cacheData) => {
  if (cacheData.length === 0) {
    return -1
  }
  return cacheData.findIndex(item => {
    return item.apiDataString === apiDataString
  })
}

...
  if (statusCode == 200 && data.code == 0) {
    if (o.isCache) { // 缓存数据
      cacheData.push({
        apiDataString: getApiDataString(api,oData), // 不直接取o.data是因为get请求时formatRequestParams把o.data转化了
        data
      })
      if (cacheData.length > cacheDataMaxLength) {
        cacheData.shift()
      }
    }
    return Promise.resolve(data)
  }
...

// 获取api和请求参数转字符串后的字符串集合
const getApiDataString = (api, data) => {
  data && delete data['_']
  return `${api}${JSON.stringify(data)}`
}

// 判断是否要取缓存
const requestCacheWrapper = async (api, o: RequestOptions, options?: AuthRequestExtensionOptions) => {
  if (o.isCache) {
    let apiDataString = getApiDataString(api, o.data)
    let cacheIndex = getCacheIndex(apiDataString,cacheData)
    if (cacheIndex !== -1) {
      // 取完数据后让数据在数组最后一位(经常用的数据放在数组末尾防止删除)
      let resData = cacheData.splice(cacheIndex, 1)
      cacheData.push(resData[0])
      return resData[0].data
    } else {
      return request(api, o, options)
    }
  } else {
    return request(api, o, options)
  }
}

api

export const getData = (data, isCache: boolean = false) => {
  return request('/data/getdata', {
    method: 'POST',
    data,
    isCache
  })
}

接口调用

getData(data, true)