国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

用ahooks如何解決用戶多次提交方法?

3403771864 / 483人閱讀

  在項(xiàng)目開(kāi)發(fā)中,要求可以實(shí)現(xiàn)客戶多次提交,這樣的要求如何實(shí)現(xiàn)?

  實(shí)現(xiàn)方法很多,比如添加 loading,在第一次點(diǎn)擊之后就無(wú)法再次點(diǎn)擊。另外一種方法就是給請(qǐng)求異步函數(shù)添加上一個(gè)靜態(tài)鎖,防止并發(fā)產(chǎn)生。這就是 ahooks 的 useLockFn 做的事情。

  useLockFn

  useLockFn用于給一個(gè)異步函數(shù)增加競(jìng)態(tài)鎖,防止并發(fā)執(zhí)行。

  它的源碼比較簡(jiǎn)單,如下所示:

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

  這里的入?yún)⑹钱惒胶瘮?shù),返回的是一個(gè)增加了競(jìng)態(tài)鎖的函數(shù)。通過(guò) lockRef 做一個(gè)標(biāo)識(shí)位,初始化的時(shí)候它的值為 false。當(dāng)正在請(qǐng)求,則設(shè)置為 true,可以影響下次再調(diào)用這個(gè)函數(shù)的時(shí)候,就直接 return,不執(zhí)行原函數(shù),從而達(dá)到加鎖的目的。

  缺點(diǎn)

  就雜每一個(gè)需要添加競(jìng)態(tài)鎖的請(qǐng)求異步函數(shù)都手動(dòng)加一遍。那如何解決?

  答案是可以通過(guò) axios 自動(dòng)取消重復(fù)請(qǐng)求。

  axios 自動(dòng)取消重復(fù)請(qǐng)求

  axios 取消請(qǐng)求

  對(duì)于原生的 XMLHttpRequest 對(duì)象發(fā)起的 HTTP 請(qǐng)求,可以調(diào)用 XMLHttpRequest 對(duì)象的 abort 方法。

  那么我們項(xiàng)目中常用的 axios 呢?它其實(shí)底層也是用的 XMLHttpRequest 對(duì)象,它對(duì)外暴露取消請(qǐng)求的 API 是 CancelToken??梢允褂萌缦拢骸?/p>

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

  另外一種使用的方法是調(diào)用 CancelToken 的構(gòu)造函數(shù)來(lái)創(chuàng)建 CancelToken,具體使用如下:

 

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

  如何自動(dòng)取消重復(fù)的請(qǐng)求

  怎么實(shí)現(xiàn)自動(dòng)取消呢?答案是通過(guò) axios 的攔截器。

  請(qǐng)求攔截器:該類攔截器的作用是在請(qǐng)求發(fā)送前統(tǒng)一執(zhí)行某些操作,比如在請(qǐng)求頭中添加 token 相關(guān)的字段。

  響應(yīng)攔截器:該類攔截器的作用是在接收到服務(wù)器響應(yīng)后統(tǒng)一執(zhí)行某些操作,比如發(fā)現(xiàn)響應(yīng)狀態(tài)碼為 401 時(shí),自動(dòng)跳轉(zhuǎn)到登錄頁(yè)。

  就看看做到方法:

  第一步,定義幾個(gè)重要的輔助函數(shù)。

  generateReqKey:用于根據(jù)當(dāng)前請(qǐng)求的信息,生成請(qǐng)求 Key。只有 key 相同才會(huì)判定為是重復(fù)請(qǐng)求。這一點(diǎn)很重要,而且可能跟具體的業(yè)務(wù)場(chǎng)景有關(guān),比如有一種請(qǐng)求,輸入框模糊搜索,用戶高頻輸入關(guān)鍵字,一次性發(fā)出多個(gè)請(qǐng)求,可能先發(fā)出的請(qǐng)求,最后才響應(yīng),導(dǎo)致實(shí)際搜索結(jié)果與預(yù)期不符。這種其實(shí)就只需要根據(jù) URL 和請(qǐng)求方法判定其為重復(fù)請(qǐng)求,然后取消之前的請(qǐng)求就可以了。

  這里我認(rèn)為,如果有需要的話,可以暴露一個(gè) API 給開(kāi)發(fā)者進(jìn)行自定義重復(fù)的規(guī)則。這里我們先根據(jù)請(qǐng)求方法、url、以及參數(shù)生成唯一的 key 去做。

  function generateReqKey(config) {
  const { method, url, params, data } = config;
  return [method, url, Qs.stringify(params), Qs.stringify(data)].join("&");
  }

  addPendingRequest。用于把當(dāng)前請(qǐng)求信息添加到 pendingRequest 對(duì)象中。 

 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。檢查是否存在重復(fù)請(qǐng)求,若存在則取消已發(fā)的請(qǐng)求。

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

  第二步,添加請(qǐng)求攔截器。

   axios.interceptors.request.use(
  function (config) {
  removePendingRequest(config); // 檢查是否存在重復(fù)請(qǐng)求,若存在則取消已發(fā)的請(qǐng)求
  addPendingRequest(config); // 把當(dāng)前請(qǐng)求信息添加到pendingRequest對(duì)象中
  return config;
  },
  (error) => {
  return Promise.reject(error);
  }
  );

  第二步,添加響應(yīng)攔截器。

  axios.interceptors.response.use(
  (response) => {
  removePendingRequest(response.config); // 從pendingRequest對(duì)象中移除請(qǐng)求
  return response;
  },
  (error) => {
  removePendingRequest(error.config || {}); // 從pendingRequest對(duì)象中移除請(qǐng)求
  if (axios.isCancel(error)) {
  console.log("已取消的重復(fù)請(qǐng)求:" + error.message);
  } else {
  // 添加異常處理
  }
  return Promise.reject(error);
  }
  );

  到這里就可以通過(guò) axios 完成了自動(dòng)取消重復(fù)請(qǐng)求的功能。

  思考與總結(jié)

  useLockFn 也可以讓 hook或方法給請(qǐng)求函數(shù)添加競(jìng)態(tài)鎖的方式解決重復(fù)請(qǐng)求的問(wèn)題??蛇@個(gè)很需要依賴于開(kāi)發(fā)者的習(xí)慣,假如沒(méi)有一些規(guī)則的約束,很難避免問(wèn)題。

  我們?cè)谕ㄟ^(guò) axios 攔截器以及其 CancelToken 功能,這樣就能夠在攔截器中自動(dòng)將已發(fā)的請(qǐng)求取消,其實(shí)我們也要注意的是有一些接口就是需要重復(fù)發(fā)送請(qǐng)求,可以考慮加一下白名單功能,讓請(qǐng)求不進(jìn)行取消。


文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/128257.html

相關(guān)文章

  • ahooks正式發(fā)布React Hooks工具庫(kù)

      起因  社會(huì)在不斷的向前,技術(shù)也在不斷的完善進(jìn)步。從 React Hooks 正式發(fā)布到現(xiàn)在,越來(lái)越多的項(xiàng)目正在使用 Function Component 替代 Class Component,Hooks 這一新特性也逐漸被廣泛的使用。 這樣的解析是不是很熟悉,在日常中時(shí)常都有用到,但也有一個(gè)可以解決這樣重復(fù)的就是對(duì)數(shù)據(jù)請(qǐng)求的邏輯處理,對(duì)防抖節(jié)流的邏輯處理等。 另一方面,由于 Hoo...

    3403771864 評(píng)論0 收藏0
  • 關(guān)于ahooks封裝cookie localStorage sessionStorage方法

      之所以講這篇文章主要是為了加深對(duì) React hooks 的理解。  因此,先要學(xué)習(xí)如何抽象自定義 hooks。構(gòu)建屬于自己的 React hooks 工具庫(kù)。  且培養(yǎng)閱讀學(xué)習(xí)源碼的習(xí)慣,工具庫(kù)是一個(gè)對(duì)源碼閱讀不錯(cuò)的選擇?! ‖F(xiàn)在看下ahooks 是怎么封裝 cookie/localStorage/sessionStorage 的?! ookie  ahooks 封裝了 useCookie...

    3403771864 評(píng)論0 收藏0
  • 解析ahooks整體架構(gòu)及React工具庫(kù)源碼

     這是講 ahooks 源碼的第一篇文章,簡(jiǎn)要就是以下幾點(diǎn):  加深對(duì) React hooks 的理解?! W(xué)習(xí)如何抽象自定義 hooks。構(gòu)建屬于自己的 React hooks 工具庫(kù)。  培養(yǎng)閱讀學(xué)習(xí)源碼的習(xí)慣,工具庫(kù)是一個(gè)對(duì)源碼閱讀不錯(cuò)的選擇?! ∽ⅲ罕鞠盗袑?duì) ahooks 的源碼解析是基于v3.3.13。自己 folk 了一份源碼,主要是對(duì)源碼做了一些解讀,可見(jiàn)詳情。  第一篇主要介紹 a...

    3403771864 評(píng)論0 收藏0
  • 詳解ahooks解決React閉包問(wèn)題方法

      想必大家都能看得懂的源碼 ahooks 整體架構(gòu)篇,且可以使用插件化機(jī)制優(yōu)雅的封裝你的請(qǐng)求hook,現(xiàn)在我們就探討下ahooks 是怎么解決 React 的閉包問(wèn)題的??! eact 的閉包問(wèn)題  先來(lái)看一個(gè)例子:  importReact,{useState,useEffect}from"react";   exportdefault()=>{   const[c...

    3403771864 評(píng)論0 收藏0
  • Java與groovy混編 —— 一種兼顧接口清晰和實(shí)現(xiàn)敏捷的開(kāi)發(fā)方式

    摘要:原文鏈接有大量平均水平左右的工人可被選擇參與進(jìn)來(lái)這意味著好招人有成熟的大量的程序庫(kù)可供選擇這意味著大多數(shù)項(xiàng)目都是既有程序庫(kù)的拼裝,標(biāo)準(zhǔn)化程度高而定制化場(chǎng)景少開(kāi)發(fā)工具測(cè)試工具問(wèn)題排查工具完善,成熟基本上沒(méi)有團(tuán)隊(duì)愿意在時(shí)間緊任務(wù)重的項(xiàng)目情況 原文鏈接:http://pfmiles.github.io/blog/java-groovy-mixed/ 有大量平均水平左右的工人可被選擇、參與...

    LittleLiByte 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<