溫馨提示×

溫馨提示×

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

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

Axios中怎么取消重復(fù)請求

發(fā)布時間:2021-08-02 15:57:35 來源:億速云 閱讀:133 作者:Leah 欄目:web開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)Axios中怎么取消重復(fù)請求,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

一、如何取消請求

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

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

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

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

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

const CancelToken = axios.CancelToken; let cancel;  axios.get('/user/12345', {   cancelToken: new CancelToken(function executor(c) {     cancel = c;   }) });  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ù)的請求:

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

當(dāng)出現(xiàn)重復(fù)請求的時候,我們就可以使用 cancel 函數(shù)來取消前面已經(jīng)發(fā)出的請求,在取消請求之后,我們還需要把取消的請求從 pendingRequest  中移除?,F(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;

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

addPendingRequest:用于把當(dāng)前請求信息添加到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:檢查是否存在重復(fù)請求,若存在則取消已發(fā)的請求。

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

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

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

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

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

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

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

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

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

Axios中怎么取消重復(fù)請求

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

 Axios中怎么取消重復(fù)請求

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

四、CancelToken 的工作原理

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

new axios.CancelToken((cancel) => {   if (!pendingRequest.has(requestKey)) {     pendingRequest.set(requestKey, cancel);   } })

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

// lib/cancel/CancelToken.js function CancelToken(executor) {   if (typeof executor !== 'function') {     throw new TypeError('executor must be a function.');   }    var resolvePromise;   this.promise = new Promise(function promiseExecutor(resolve) {     resolvePromise = resolve;   });    var token = this;   executor(function cancel(message) { // 設(shè)置cancel對象     if (token.reason) {       return; // Cancellation has already been requested     }     token.reason = new Cancel(message);     resolvePromise(token.reason);   }); }

由以上代碼可知,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 文件中找到了答案:

// lib/adapters/xhr.js  if (config.cancelToken) {   config.cancelToken.promise.then(function onCanceled(cancel) {     if (!request) { return; }     request.abort(); // 取消請求     reject(cancel);     request = null;   }); }

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

 Axios中怎么取消重復(fù)請求

關(guān)于Axios中怎么取消重復(fù)請求就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI