傳送新請求,取消上一次pending狀態的同一請求

度vApud發表於2022-11-24

src/utils/request.js



import axios from 'axios'

// 方法一:請求方式、請求 URL、請求引數都一樣時,視為同一請求
// function generateReqKey(config) {
//   const { method, url, params, data } = config;
//   return [method, url, JSON.stringify(params), JSON.stringify(data)].join("&");
// }
// 方法二:請求方式、請求 URL視為同一請求,(不判斷引數是否一致,列表頁在網路不穩定時,存在先發起的page:2資料比後發起的page:3資料後返回,導致顯示頁碼3,展示的是頁碼2的資料)
//用於根據當前請求的資訊,生成請求 Key
function generateReqKey(config) {
  const { method, url } = config;
  return [method, url].join("&");
}

//用於把當前請求資訊新增到pendingRequest物件中
const pendingRequest = new Map();
function addPendingRequest(config) {
  const requestKey = generateReqKey(config);
  config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
    if (!pendingRequest.has(requestKey)) {
      pendingRequest.set(requestKey, cancel);
    }
  });
}

//檢查是否存在重複請求,若存在則取消已發的請求
function removePendingRequest(config) {
  const requestKey = generateReqKey(config);
  if (pendingRequest.has(requestKey)) {
    const cancelToken = pendingRequest.get(requestKey);
    cancelToken(requestKey);
    pendingRequest.delete(requestKey);
  }
}


// 建立axios例項
const service = axios.create({
  baseURL: '介面地址',
  timeout: 30000
})

// request攔截器
service.interceptors.request.use(
  config => {
    removePendingRequest(config); // 檢查是否存在重複請求,若存在則取消已發的請求
    addPendingRequest(config); // 把當前請求資訊新增到pendingRequest物件中
    return config;

  },
  error => {
    Promise.reject(error)
  }
)

// response 攔截器
service.interceptors.response.use(
  response => {

    removePendingRequest(response.config); // 從pendingRequest物件中移除請求

    return response.data
  },
  error => {
    removePendingRequest(error.config || {}); // 從pendingRequest物件中移除請求
    if (axios.isCancel(error)) {
      console.log("已取消的重複請求:" + error.message);
    } else {
      // 新增異常處理
    }

    return Promise.reject(error)
  }
)

export default service

src/api/index.js

import request from '@/utils/request'

// 驗證碼
export function getCode(data) {
    return request({
        url: '/support/country',
        method: 'get',
        params: data
    })
}

頁面呼叫

<template>
  <div id="app">
    <button @click="send()">請求</button>
  </div>
</template>

<script>
import { getCode } from "@/api/index.js";

export default {
  name: "App",

  methods: {
//重複點選,將會取消上一次pending狀態的同一請求
    send() {
      getCode().then((res) => {
        console.log("res", res);
      });
    }
   
  },
};
</script>

<style></style>

相關文章