promise并发缓存(ts)

应用场景:一个页面里有好几个下拉选择框,选项都是接口提供的常量, 前端拿到以后自己再根据类型挑出来,所以这种情况我们肯定不能每个下拉框都去调一次接口,只能是寄托缓存机制了.

// 缓存池就是一个map,存储接口数据的地方,将接口的路径和参数拼到一块作为key

import axios, { AxiosRequestConfig } from 'axios'
import qs from 'qs'

interface MyRequestConfig extends AxiosRequestConfig {
  needCache?: boolean
}
// 定义一下回调的格式
interface RequestCallback {
  onSuccess: (data: any) => void
  onError: (error: any) => void
}

// 存储缓存当前状态,相当于挂牌子的地方。判断缓存前的状态,完成就获取数据,pending就等待其缓存完成
const statusMap = new Map<string, 'pending' | 'complete'>()

const cacheMap = new Map() // 缓存池, key 和 value (后端返回的值)

const callbackMap = new Map<string, RequestCallback[]>() // 缓存回调

// 为params是 GET 方式穿的参数,我们的缓存一般都是 GET 接口用的
const generateCacheKey = (config: MyRequestConfig) =>
  config.url + '?' + qs.stringify(config.params)

export function sendRequest(request: MyRequestConfig) {
  const cacheKey = generateCacheKey(request)

  // 判断是否需要缓存
  if (request.needCache) {
    if (statusMap.has(cacheKey)) {
      const currentStatus = statusMap.get(cacheKey)

      // 判断当前的接口缓存状态,如果是 complete ,则代表缓存完成
      if (currentStatus === 'complete') {
        return Promise.resolve(cacheMap.get(cacheKey))
      }

      // 如果是 pending ,则代表正在请求中,这里就等, 缓存回调
      if (currentStatus === 'pending') {
        return new Promise((resolve, reject) => {
          if (callbackMap.has(cacheKey)) {
            callbackMap.get(cacheKey)!.push({
              onSuccess: resolve,
              onError: reject,
            })
          } else {
            callbackMap.set(cacheKey, [
              {
                onSuccess: resolve,
                onError: reject,
              },
            ])
          }
        })
      }
    }
    statusMap.set(cacheKey, 'pending')
  }

  return axios(request).then(
    (res) => {
      // 这里简单判断一下,200就算成功了
      if (res.status === 200) {
        statusMap.set(cacheKey, 'complete')
        cacheMap.set(cacheKey, res)
      } else {
        // 不成功
        statusMap.delete(cacheKey)
      }
      // 触发resolve的回调函数
      if (callbackMap.has(cacheKey)) {
        callbackMap
          .get(cacheKey)!
          .forEach((callback) => callback.onSuccess(res))
      }
      callbackMap.delete(cacheKey)
      return res
    },
    (error) => {
      statusMap.delete(cacheKey)
      if (callbackMap.has(cacheKey)) {
        callbackMap
          .get(cacheKey)!
          .forEach((callback) => callback.onError(error))
        statusMap.delete(cacheKey)
      }

      // 这里要返回 Promise.reject(error),才能被catch捕捉到
      return Promise.reject(error)
    }
  )
}

export default sendRequest


// 调用
import sendRequest from './utils/concurrentRequest'
const getArticleList = (params: any) =>
  sendRequest({
    needCache: true, // 使用缓存
    url: 'https://mock.apifox.cn/m1/2081776-0-default/mytest',
    method: 'get',
    params,
  })

getArticleList({
  page: 1,
  pageSize: 10,
}).then((res) => {
  console.log(res)
})

getArticleList({
  page: 1,
  pageSize: 10,
}).then((res) => {
  console.log(res)
})
  • 实现效果: 获得两组返回console, 请求只发送一次。

参考: 微信公众号—vue中文社区

你可能感兴趣的:(缓存,数学建模)