前端防止重复请求-缓存promise方案

380 阅读1分钟

防止重复请求一直是之前想去实现的功能,最近又刷到了掘友的文章,借鉴了下思路,具体实现采用了缓存promise的方案,让代码更加简洁。

代码


const vAxios = axios.create({
  baseURL: '/api',
})

// 根据请求生成对应的key
function generateReqKey(config, hash) {
  const { method, url, params, data } = config
  return [method, url, JSON.stringify(params), JSON.stringify(data), hash].join('&')
}

const pendingRequest = new Map()

// 添加请求拦截器
vAxios.interceptors.request.use(
  (config) => {
    return config
  },
  (err) => {
    return Promise.reject(err)
  }
)

// 添加响应拦截器
vAxios.interceptors.response.use(
  (res) => {
    return Promise.resolve('success')
  },
  (err) => {
    return Promise.reject('error')
  }
)

function http(config) {
  const hash = location.hash
  // 生成请求Key
  const reqKey = generateReqKey(config, hash)
  if (pendingRequest.has(reqKey)) {
    return pendingRequest.get(reqKey)
  }
  const instance = vAxios(config)
  pendingRequest.set(reqKey, instance)
  instance.finally(() => {
    pendingRequest.delete(reqKey)
  })
  return instance
}

export default http

使用案例

import axios from './axios'

export function login(params) {
  return axios({
    url: '/login',
    params,
  })
}

vue页面使用

<template>
  <div @click="click1">click1</div>
  <div @click="click2">click2</div>
</template>

<script setup>
import { login } from '@/api/system/api'

function click1() {
  login({ a: 1, b: 2 }).then(
    (res) => {
      console.log('1')
    },
    (err) => {
      console.log('1')
    }
  )
}
function click2() {
  login({ a: 1, b: 2 }).then(
    (res) => {
      console.log('2')
    },
    (err) => {
      console.log('2')
    }
  )
}
</script>

最后附上原文链接juejin.cn/post/734184…