成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊Axios 如何取消重復(fù)請求?

開發(fā) 前端
Axios 是一個基于 Promise 的 HTTP 客戶端,同時支持瀏覽器和 Node.js 環(huán)境。它是一個優(yōu)秀的 HTTP 客戶端,被廣泛地應(yīng)用在大量的 Web 項目中。

[[391270]]

在 Web 項目開發(fā)過程中,我們經(jīng)常會遇到重復(fù)請求的場景,如果系統(tǒng)不對重復(fù)的請求進(jìn)行處理,則可能會導(dǎo)致系統(tǒng)出現(xiàn)各種問題。比如重復(fù)的 post 請求可能會導(dǎo)致服務(wù)端產(chǎn)生兩筆記錄。那么重復(fù)請求是如何產(chǎn)生的呢?這里我們舉 2 個常見的場景:

  • 假設(shè)頁面中有一個按鈕,用戶點(diǎn)擊按鈕后會發(fā)起一個 AJAX 請求。如果未對該按鈕進(jìn)行控制,當(dāng)用戶快速點(diǎn)擊按鈕時,則會發(fā)出重復(fù)請求。
  • 假設(shè)在考試結(jié)果查詢頁面中,用戶可以根據(jù) “已通過”、“未通過” 和 “全部” 3 種查詢條件來查詢考試結(jié)果。如果請求的響應(yīng)比較慢,當(dāng)用戶在不同的查詢條件之前快速切換時,就會產(chǎn)生重復(fù)請求。

既然已經(jīng)知道重復(fù)請求是如何產(chǎn)生的,也知道了它會帶來一些問題。接下來,阿寶哥將以 Axios 為例,帶大家來一起解決重復(fù)請求的問題。

一、如何取消請求

Axios 是一個基于 Promise 的 HTTP 客戶端,同時支持瀏覽器和 Node.js 環(huán)境。它是一個優(yōu)秀的 HTTP 客戶端,被廣泛地應(yīng)用在大量的 Web 項目中。對于瀏覽器環(huán)境來說,Axios 底層是利用 XMLHttpRequest 對象來發(fā)起 HTTP 請求。如果要取消請求的話,我們可以通過調(diào)用 XMLHttpRequest 對象上的 abort 方法來取消請求:

  1. let xhr = new XMLHttpRequest(); 
  2. xhr.open("GET""https://developer.mozilla.org/"true); 
  3. xhr.send(); 
  4. setTimeout(() => xhr.abort(), 300); 

而對于 Axios 來說,我們可以通過 Axios 內(nèi)部提供的 CancelToken 來取消請求:

  1. const CancelToken = axios.CancelToken; 
  2. const source = CancelToken.source(); 
  3.  
  4. axios.post('/user/12345', { 
  5.   name'semlinker' 
  6. }, { 
  7.   cancelToken: source.token 
  8. }) 
  9.  
  10. source.cancel('Operation canceled by the user.'); // 取消請求,參數(shù)是可選的 

此外,你也可以通過調(diào)用 CancelToken 的構(gòu)造函數(shù)來創(chuàng)建 CancelToken,具體如下所示:

  1. const CancelToken = axios.CancelToken; 
  2. let cancel; 
  3.  
  4. axios.get('/user/12345', { 
  5.   cancelToken: new CancelToken(function executor(c) { 
  6.     cancel = c; 
  7.   }) 
  8. }); 
  9.  
  10. cancel(); // 取消請求 

現(xiàn)在我們已經(jīng)知道在 Axios 中如何使用 CancelToken 來取消請求了,那么 CancelToken內(nèi)部是如何工作的呢?這里我們先記住這個問題,后面阿寶哥將為你們揭開 CancelToken背后的秘密。接下來,我們來分析一下如何判斷重復(fù)請求。

二、如何判斷重復(fù)請求當(dāng)請求

方式、請求 URL 地址和請求參數(shù)都一樣時,我們就可以認(rèn)為請求是一樣的。因此在每次發(fā)起請求時,我們就可以根據(jù)當(dāng)前請求的請求方式、請求 URL 地址和請求參數(shù)來生成一個唯一的 key,同時為每個請求創(chuàng)建一個專屬的 CancelToken,然后把 key 和 cancel 函數(shù)以鍵值對的形式保存到 Map 對象中,使用 Map 的好處是可以快速的判斷是否有重復(fù)的請求:

  1. import qs from 'qs' 
  2.  
  3. const pendingRequest = new Map(); 
  4. // GET -> params;POST -> data 
  5. const requestKey = [method, url, qs.stringify(params), qs.stringify(data)].join('&');  
  6. const cancelToken = new CancelToken(function executor(cancel) { 
  7.   if(!pendingRequest.has(requestKey)){ 
  8.     pendingRequest.set(requestKey, cancel); 
  9.   } 
  10. }) 

當(dāng)出現(xiàn)重復(fù)請求的時候,我們就可以使用 cancel 函數(shù)來取消前面已經(jīng)發(fā)出的請求,在取消請求之后,我們還需要把取消的請求從 pendingRequest 中移除。現(xiàn)在我們已經(jīng)知道如何取消請求和如何判斷重復(fù)請求,下面我們來介紹如何取消重復(fù)請求。

三、如何取消重復(fù)請求

因為我們需要對所有的請求都進(jìn)行處理,所以我們可以考慮使用 Axios 的攔截器機(jī)制來實現(xiàn)取消重復(fù)請求的功能。Axios 為開發(fā)者提供了請求攔截器和響應(yīng)攔截器,它們的作用如下:

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

3.1 定義輔助函數(shù)

在配置請求攔截器和響應(yīng)攔截器前,阿寶哥先來定義 3 個輔助函數(shù):

generateReqKey:用于根據(jù)當(dāng)前請求的信息,生成請求 Key;

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

addPendingRequest:用于把當(dāng)前請求信息添加到pendingRequest對象中;

  1. const pendingRequest = new Map(); 
  2. function addPendingRequest(config) { 
  3.   const requestKey = generateReqKey(config); 
  4.   config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => { 
  5.     if (!pendingRequest.has(requestKey)) { 
  6.        pendingRequest.set(requestKey, cancel); 
  7.     } 
  8.   }); 

removePendingRequest:檢查是否存在重復(fù)請求,若存在則取消已發(fā)的請求。

  1. function removePendingRequest(config) { 
  2.   const requestKey = generateReqKey(config); 
  3.   if (pendingRequest.has(requestKey)) { 
  4.      const cancelToken = pendingRequest.get(requestKey); 
  5.      cancelToken(requestKey); 
  6.      pendingRequest.delete(requestKey); 
  7.   } 

創(chuàng)建好 generateReqKey、addPendingRequest 和 removePendingRequest 函數(shù)之后,我們就可以設(shè)置請求攔截器和響應(yīng)攔截器了。

3.2 設(shè)置請求攔截器

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

3.3 設(shè)置響應(yīng)攔截器

  1. axios.interceptors.response.use( 
  2.   (response) => { 
  3.      removePendingRequest(response.config); // 從pendingRequest對象中移除請求 
  4.      return response; 
  5.    }, 
  6.    (error) => { 
  7.       removePendingRequest(error.config || {}); // 從pendingRequest對象中移除請求 
  8.       if (axios.isCancel(error)) { 
  9.         console.log("已取消的重復(fù)請求:" + error.message); 
  10.       } else { 
  11.         // 添加異常處理 
  12.       } 
  13.       return Promise.reject(error); 
  14.    } 
  15. ); 

由于完整的示例代碼內(nèi)容比較多,阿寶哥就不放具體的代碼了。感興趣的小伙伴,可以訪問以下地址瀏覽示例代碼。

  1. 完整的示例代碼:https://gist.github.com/semlinker/e426780664f0186db434882f1e27ac3a 

這里我們來看一下 Axios 取消重復(fù)請求示例的運(yùn)行結(jié)果: 


 從上圖可知,當(dāng)出現(xiàn)重復(fù)請求時,之前已發(fā)送且未完成的請求會被取消掉。下面我們用一張流程圖來總結(jié)一下取消重復(fù)請求的處理流程:

 

最后,我們來回答前面留下的問題,即 CancelToken 內(nèi)部是如何工作的?

四、CancelToken 的工作原理

在前面的示例中,我們是通過調(diào)用 CancelToken 構(gòu)造函數(shù)來創(chuàng)建 CancelToken 對象:

  1. new axios.CancelToken((cancel) => { 
  2.   if (!pendingRequest.has(requestKey)) { 
  3.     pendingRequest.set(requestKey, cancel); 
  4.   } 
  5. }) 

所以接下來,我們來分析 CancelToken 構(gòu)造函數(shù),該函數(shù)被定義在 lib/cancel/CancelToken.js 文件中:

  1. // lib/cancel/CancelToken.js 
  2. function CancelToken(executor) { 
  3.   if (typeof executor !== 'function') { 
  4.     throw new TypeError('executor must be a function.'); 
  5.   } 
  6.  
  7.   var resolvePromise; 
  8.   this.promise = new Promise(function promiseExecutor(resolve) { 
  9.     resolvePromise = resolve; 
  10.   }); 
  11.  
  12.   var token = this; 
  13.   executor(function cancel(message) { // 設(shè)置cancel對象 
  14.     if (token.reason) { 
  15.       return; // Cancellation has already been requested 
  16.     } 
  17.     token.reason = new Cancel(message); 
  18.     resolvePromise(token.reason); 
  19.   }); 

由以上代碼可知,cancel 對象是一個函數(shù),當(dāng)我們調(diào)用該函數(shù)后,會創(chuàng)建 Cancel 對象并調(diào)用 resolvePromise 方法。該方法執(zhí)行后,CancelToken 對象上 promise 屬性所指向的 promise 對象的狀態(tài)將變?yōu)? resolved。那么這樣做的目的是什么呢?這里我們從 lib/adapters/xhr.js 文件中找到了答案:

  1. // lib/adapters/xhr.js  
  2. if (config.cancelToken) { 
  3.   config.cancelToken.promise.then(function onCanceled(cancel) { 
  4.     if (!request) { return; } 
  5.     request.abort(); // 取消請求 
  6.     reject(cancel); 
  7.     request = null
  8.   }); 

看完上述的內(nèi)容,可能有的小伙伴還不是很能理解 CancelToken 的工作原理,所以阿寶哥又畫了一張圖來幫助大家理解 CancelToken 的工作原理:

 

五、總結(jié)

本文介紹了在 Axios 中如何取消重復(fù)請求及 CancelToken 的工作原理,在后續(xù)的文章中,阿寶哥將會介紹在 Axios 中如何設(shè)置數(shù)據(jù)緩存,感興趣的小伙伴不要錯過喲。如果你想了解 Axios 中 HTTP 攔截器及 HTTP 適配器的設(shè)計與實現(xiàn),可以閱讀 77.9K 的 Axios 項目有哪些值得借鑒的地方 這篇文章。

六、參考資源

  • Github - Axios
  • MDN - XMLHttpRequest
  • 77.9K 的 Axios 項目有哪些值得借鑒的地方

 

責(zé)任編輯:姜華 來源: 全棧修仙之路
相關(guān)推薦

2024-08-27 08:55:32

Axios底層網(wǎng)絡(luò)

2024-08-12 12:32:53

Axios機(jī)制網(wǎng)絡(luò)

2022-11-17 07:43:13

2021-06-17 09:32:39

重復(fù)請求并發(fā)請求Java

2021-04-22 05:37:14

Axios 開源項目HTTP 攔截器

2021-04-12 05:55:29

緩存數(shù)據(jù)Axios

2021-07-27 14:50:15

axiosHTTP前端

2025-01-24 00:00:00

數(shù)據(jù)RoaringBitmap

2024-06-05 08:42:24

2024-06-06 08:46:37

2022-06-09 09:20:41

ahooksaxios

2024-08-26 13:23:26

2025-05-27 05:00:00

fetchAPI網(wǎng)絡(luò)

2021-01-25 06:53:59

前端AJAX技術(shù)熱點(diǎn)

2025-04-27 01:22:00

QPS高并發(fā)MySQL

2023-08-09 09:11:57

算法分發(fā)效果

2025-01-23 00:00:00

JMMJava

2021-05-17 08:11:24

Axios 開源項目HTTP 攔截器

2022-03-01 07:52:38

鏈表指針節(jié)點(diǎn)

2020-05-06 22:07:53

UbuntuLinux操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 一区二区国产精品 | 国产精品成人一区二区三区 | 免费看黄色小视频 | 欧美日韩视频在线播放 | 日韩视频1 | 日日摸日日碰夜夜爽亚洲精品蜜乳 | 欧美 日韩 在线播放 | 在线免费国产视频 | 中文字幕在线观看一区 | 亚洲精品一二三 | 国产aa | 一区二区三区免费在线观看 | 美国黄色毛片 | 国产一级在线 | 欧美成人第一页 | 国产免费一区二区三区 | 韩国成人在线视频 | 成年人网站国产 | 日韩激情一区 | 欧美一区二区三区四区五区无卡码 | 日韩一区二区黄色片 | 亚洲精品一区二区三区在线观看 | 伊人久久大香线 | 亚洲一区中文 | 一区二区三区电影网 | 特级毛片爽www免费版 | 久久精品在线播放 | 一区二区免费看 | 国产精品一区在线播放 | 91久久久久 | 免费a网| 在线播放第一页 | 精品国产乱码久久久久久丨区2区 | 亚洲人成人一区二区在线观看 | 国产人久久人人人人爽 | 精品精品视频 | 久久精品国产一区二区电影 | 一区二区三区欧美大片 | 久久久这里都是精品 | 天天色官网 | 久久高清国产视频 |