axios (十一) -- 取消重复请求

1、场景

2种场景:
假设页面中有一个按钮,用户点击按钮后会发起请求。如果没有对该按钮进行控制,当用户快速点击按钮时,会发出重复请求。
假设在工单结果查询页面中,用户可以根据 “已审批”、“未审批” 和 “全部” 3 种查询条件来查询工单结果。如果请求的响应比较慢,当用户在不同的查询条件之前快速切换时,就会产生重复请求。

处理有三种情况:(第一次请求A,第二次请求B)
1、取消第一次A ,请求第二次B
2、请求第一次A,取消第二次B
3、请求第一次A,取消第二次B,将A请求结果给B

这里用第二种

理解小 tips:

1、定义 pendingRequests 为 map 对象的目的是为了方便我们查询它是否包含某个 key,以及添加和删除 key。添加 key 时,对应的 value 可以设置用户自定义的一些功能参数。
2、 config 是 axios 拦截器中的参数,包含当前请求的信息
3、 在请求发出前检查当前请求是否重复
4、 在请求拦截器中,生成上面的 requestKey,检查 pendingRequests 对象中是否包含当前请求的 requestKey: 有:说明是重复的请求,cancel 掉当前请求;没有:把 requestKey 添加到 pendingRequests 对象中

请求拦截

1、检查是否存在重复请求,若存在则取消已发的请求
2、把当前请求添加到pendingRequest对象中

2、代码

<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Axios 取消重复请求示例</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/qs/6.9.6/qs.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
  </head>
  <body>
    <h3>Axios 取消重复请求示例</h3>
    <button onclick="sendRequest()">发起请求</button>
    <script>
        // 判断重复,存储所有 pending 状态的请求
      const pendingRequest = new Map();

      // 根据 url、method、params 等生成唯一标识,大家可以自定义自己的生成规则    
      function generateReqKey(config) {
        const { method, url, params, data } = config;
        return `${url}/${JSON.stringify(params)}/${JSON.stringify(data)}&request_type=${method}`;;
      }

      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 cancel = pendingRequest.get(requestKey);
          cancel(requestKey);
          pendingRequest.delete(requestKey);
        }
      }
    // 取消重复
    // 请求拦截器:请求发送前统一执行某些操作,比如在请求头中添加 token 字段。
    // 响应拦截器:接收到服务器响应后统一执行某些操作,比如发现响应状态码为 401 时,自动跳转到登录页。
    axios.interceptors.request.use(
        function (config) {
          removePendingRequest(config); // 检查是否存在重复请求,若存在则取消已发的请求
          addPendingRequest(config); // 把当前请求添加到pendingRequest对象中
          return config;
        },
        (error) => {
          return Promise.reject(error);
        }
      );
      // 可以在响应拦截函数中统一处理返回码的逻辑
      axios.interceptors.response.use(
        (response) => {
          removePendingRequest(response.config); // 从pendingRequest对象中移除请求
          return response;
        },
        (error) => {
          removePendingRequest(error.config || {}); // 从pendingRequest对象中移除请求
          if (axios.isCancel(error)) {
            console.log("已取消的重复请求:" + error.message);
          } else {
            // 添加异常处理
          }
          return Promise.reject(error);
        }
      );

      async function sendRequest() {
        console.dir(pendingRequest);
        const response = await axios.get(
            "http://localhost:3000/api/user"
        );
        console.log(response.data);
      }
    </script>
  </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值