温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Axios中怎么取消重复请求

发布时间:2021-08-02 15:57:35 来源:亿速云 阅读:133 作者:Leah 栏目:web开发

这篇文章将为大家详细讲解有关Axios中怎么取消重复请求,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

一、如何取消请求

Axios 是一个基于 Promise 的 HTTP 客户端,同时支持浏览器和 Node.js 环境。它是一个优秀的 HTTP  客户端,被广泛地应用在大量的 Web 项目中。对于浏览器环境来说,Axios 底层是利用 XMLHttpRequest 对象来发起 HTTP  请求。如果要取消请求的话,我们可以通过调用 XMLHttpRequest 对象上的 abort 方法来取消请求:

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

而对于 Axios 来说,我们可以通过 Axios 内部提供的 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.'); // 取消请求,参数是可选的

此外,你也可以通过调用 CancelToken 的构造函数来创建 CancelToken,具体如下所示:

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

现在我们已经知道在 Axios 中如何使用 CancelToken 来取消请求了,那么  CancelToken内部是如何工作的呢?这里我们先记住这个问题,后面阿宝哥将为你们揭开  CancelToken背后的秘密。接下来,我们来分析一下如何判断重复请求。

二、如何判断重复请求当请求

方式、请求 URL  地址和请求参数都一样时,我们就可以认为请求是一样的。因此在每次发起请求时,我们就可以根据当前请求的请求方式、请求 URL 地址和请求参数来生成一个唯一的  key,同时为每个请求创建一个专属的 CancelToken,然后把 key 和 cancel 函数以键值对的形式保存到 Map 对象中,使用 Map  的好处是可以快速的判断是否有重复的请求:

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

当出现重复请求的时候,我们就可以使用 cancel 函数来取消前面已经发出的请求,在取消请求之后,我们还需要把取消的请求从 pendingRequest  中移除。现在我们已经知道如何取消请求和如何判断重复请求,下面我们来介绍如何取消重复请求。

三、如何取消重复请求

因为我们需要对所有的请求都进行处理,所以我们可以考虑使用 Axios 的拦截器机制来实现取消重复请求的功能。Axios  为开发者提供了请求拦截器和响应拦截器,它们的作用如下:

  • 请求拦截器:该类拦截器的作用是在请求发送前统一执行某些操作,比如在请求头中添加 token 字段。

  • 响应拦截器:该类拦截器的作用是在接收到服务器响应后统一执行某些操作,比如发现响应状态码为 401 时,自动跳转到登录页。

3.1 定义辅助函数

在配置请求拦截器和响应拦截器前,阿宝哥先来定义 3 个辅助函数:

generateReqKey:用于根据当前请求的信息,生成请求 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);   } }

创建好 generateReqKey、addPendingRequest 和 removePendingRequest  函数之后,我们就可以设置请求拦截器和响应拦截器了。

3.2 设置请求拦截器

axios.interceptors.request.use(   function (config) {     removePendingRequest(config); // 检查是否存在重复请求,若存在则取消已发的请求     addPendingRequest(config); // 把当前请求信息添加到pendingRequest对象中     return config;   },   (error) => {      return Promise.reject(error);   } );

3.3 设置响应拦截器

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

由于完整的示例代码内容比较多,阿宝哥就不放具体的代码了。感兴趣的小伙伴,可以访问以下地址浏览示例代码。

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

这里我们来看一下 Axios 取消重复请求示例的运行结果:

Axios中怎么取消重复请求

从上图可知,当出现重复请求时,之前已发送且未完成的请求会被取消掉。下面我们用一张流程图来总结一下取消重复请求的处理流程:

 Axios中怎么取消重复请求

最后,我们来回答前面留下的问题,即 CancelToken 内部是如何工作的?

四、CancelToken 的工作原理

在前面的示例中,我们是通过调用 CancelToken 构造函数来创建 CancelToken 对象:

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

所以接下来,我们来分析 CancelToken 构造函数,该函数被定义在 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) { // 设置cancel对象     if (token.reason) {       return; // Cancellation has already been requested     }     token.reason = new Cancel(message);     resolvePromise(token.reason);   }); }

由以上代码可知,cancel 对象是一个函数,当我们调用该函数后,会创建 Cancel 对象并调用 resolvePromise  方法。该方法执行后,CancelToken 对象上 promise 属性所指向的 promise 对象的状态将变为  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;   }); }

看完上述的内容,可能有的小伙伴还不是很能理解 CancelToken 的工作原理,所以阿宝哥又画了一张图来帮助大家理解 CancelToken  的工作原理:

 Axios中怎么取消重复请求

关于Axios中怎么取消重复请求就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI