中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ahooks怎么解決用戶多次提交問題

發布時間:2022-07-12 10:06:44 來源:億速云 閱讀:156 作者:iii 欄目:開發技術

這篇文章主要介紹“ahooks怎么解決用戶多次提交問題”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“ahooks怎么解決用戶多次提交問題”文章能幫助大家解決問題。

    場景

    試想一下,有這么一個場景,有一個表單,你可能多次提交,就很可能導致結果不正確。

    解決這類問題的方法有很多,比如添加 loading,在第一次點擊之后就無法再次點擊。另外一種方法就是給請求異步函數添加上一個靜態鎖,防止并發產生。這就是 ahooks 的 useLockFn 做的事情。

    useLockFn

    useLockFn 用于給一個異步函數增加競態鎖,防止并發執行。

    它的源碼比較簡單,如下所示:

    import { useRef, useCallback } from 'react';
    // 用于給一個異步函數增加競態鎖,防止并發執行。
    function useLockFn<P extends any[] = any[], V extends any = any>(fn: (...args: P) => Promise<V>) {
      // 是否現在處于一個鎖中
      const lockRef = useRef(false);
      // 返回的是增加了競態鎖的函數
      return useCallback(
        async (...args: P) => {
          // 判斷請求是否正在進行
          if (lockRef.current) return;
          // 請求中
          lockRef.current = true;
          try {
            // 執行原有請求
            const ret = await fn(...args);
            // 請求完成,狀態鎖設置為 false
            lockRef.current = false;
            return ret;
          } catch (e) {
            // 請求失敗,狀態鎖設置為 false
            lockRef.current = false;
            throw e;
          }
        },
        [fn],
      );
    }
    export default useLockFn;

    可以看到,它的入參是異步函數,返回的是一個增加了競態鎖的函數。通過 lockRef 做一個標識位,初始化的時候它的值為 false。當正在請求,則設置為 true,從而下次再調用這個函數的時候,就直接 return,不執行原函數,從而達到加鎖的目的。

    缺點

    雖然實用,但缺點很明顯,我需要給每一個需要添加競態鎖的請求異步函數都手動加一遍。那有沒有比較通用和方便的方法呢?

    答案是可以通過 axios 自動取消重復請求。

    axios 自動取消重復請求

    axios 取消請求

    對于原生的 XMLHttpRequest 對象發起的 HTTP 請求,可以調用 XMLHttpRequest 對象的 abort 方法。

    那么我們項目中常用的 axios 呢?它其實底層也是用的 XMLHttpRequest 對象,它對外暴露取消請求的 API 是 CancelToken。可以使用如下:

    const CancelToken = axios.CancelToken;
    const source = CancelToken.source();
    axios.post('/user/12345', {
      name: 'gopal'
    }, {
      cancelToken: source.token
    })
    source.cancel('Operation canceled by the user.'); // 取消請求,參數是可選的

    另外一種使用的方法是調用 CancelToken 的構造函數來創建 CancelToken,具體使用如下:

    const CancelToken = axios.CancelToken;
    let cancel;
    axios.get('/user/12345', {
      cancelToken: new CancelToken(function executor(c) {
        cancel = c;
      })
    });
    cancel(); // 取消請求

    如何自動取消重復的請求

    知道了如何取消請求,那怎么做到自動取消呢?答案是通過 axios 的攔截器。

    • 請求攔截器:該類攔截器的作用是在請求發送前統一執行某些操作,比如在請求頭中添加 token 相關的字段。

    • 響應攔截器:該類攔截器的作用是在接收到服務器響應后統一執行某些操作,比如發現響應狀態碼為 401 時,自動跳轉到登錄頁。

    具體的做法如下:

    第一步,定義幾個重要的輔助函數。

    • generateReqKey:用于根據當前請求的信息,生成請求 Key。只有 key 相同才會判定為是重復請求。這一點很重要,而且可能跟具體的業務場景有關,比如有一種請求,輸入框模糊搜索,用戶高頻輸入關鍵字,一次性發出多個請求,可能先發出的請求,最后才響應,導致實際搜索結果與預期不符。這種其實就只需要根據 URL 和請求方法判定其為重復請求,然后取消之前的請求就可以了。

    這里我認為,如果有需要的話,可以暴露一個 API 給開發者進行自定義重復的規則。這里我們先根據請求方法、url、以及參數生成唯一的 key 去做。

    function generateReqKey(config) {
      const { method, url, params, data } = config;
      return [method, url, Qs.stringify(params), Qs.stringify(data)].join("&");
    }
    • addPendingRequest。用于把當前請求信息添加到 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);
        }
      });
    }
    • removePendingRequest。檢查是否存在重復請求,若存在則取消已發的請求。

    function removePendingRequest(config) {
      const requestKey = generateReqKey(config);
      if (pendingRequest.has(requestKey)) {
         const cancelToken = pendingRequest.get(requestKey);
         cancelToken(requestKey);
         pendingRequest.delete(requestKey);
      }
    }

    第二步,添加請求攔截器。

    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);
       }
    );

    到這一步,我們就通過 axios 完成了自動取消重復請求的功能。

    關于“ahooks怎么解決用戶多次提交問題”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    青海省| 奈曼旗| 伽师县| 大余县| 东平县| 河北区| 廉江市| 南康市| 德令哈市| 龙川县| 康保县| 乐至县| 东山县| 南江县| 彰化市| 长子县| 凤台县| 周宁县| 繁昌县| 兴国县| 金乡县| 象州县| 扶风县| 西畴县| 澄城县| 平远县| 邹平县| 柏乡县| 萨嘎县| 泽库县| 东明县| 朔州市| 岳阳市| 和平区| 鹤庆县| 卢湾区| 清涧县| 阜城县| 新泰市| 望谟县| 鹿泉市|