前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Axios】:Axios 的"请求取消"特性是什么原理?

【Axios】:Axios 的"请求取消"特性是什么原理?

作者头像
WEBJ2EE
发布2021-12-26 10:09:32
2.4K0
发布2021-12-26 10:09:32
举报
文章被收录于专栏:WebJ2EEWebJ2EE

1. 背景

我们在处理前后端交互的过程中,有时需要仔细斟酌接口的请求时机(例:频繁的Tab切换、树节点切换、数据录入时,请求什么时候发?)或接口返回数据的处理时机(例:接口还没返回时就要切换路由,路由都切换走了,之前请求的数据怎么办?),避免一些无用的请求或者接口返回顺序的差异(例如:同一个按钮点了多次,如果后点的先返回,先点的后返回,怎么办?)。

常见的处理方式有:

  • 加防抖:控制请求时机。对于频繁操作,只在最后一次动作时,发出请求。
  • 锁状态:控制请求时机。直接禁止很频繁的操作,必须一个接一个。
  • 取消请求:控制请求处理时机。取消之前没返回的请求,不再处理了。

2. Axios 有“请求取消”技能

Axios 自带 cancel token API,支持“请求取消”技能

代码语言:javascript
复制
// CancelToken 的 source 工厂方法,构造出的对象含有:
// 1. token:一个 CancelToken 实例,即令牌
// 2. cancel: 一个用于取消令牌的函数。
const source = axios.CancelToken.source();

axios.get('/user/12345', {
  // 将令牌实例(即 CancelToken)注入到 axios 内部
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    // 借助 isCancel 可判定该请求异常,是不是由“请求取消”引发
    console.log('Request canceled', thrown.message);
  } else {
     // 其他类型请求异常处理...
  }
});

// 外部可调用 cancel 函数,用于取消令牌;
// axios 内部观察到令牌被取消,随即对请求进行取消;
source.cancel('Operation canceled by the user.');

3. Axios 中的 CancelToken 什么原理?

3.1. 源码在哪?

Axios 的 CancelToken API 在源码中是一个独立模块。

我们先来看 CancelToken 怎么独立使用

再研究它如何与 Axios 结合

3.2. 怎么用

用法1:利用工厂构造令牌,且基于“订阅”的API

代码语言:javascript
复制
const CancelToken = require("./CancelToken");
const isCancel = require("./isCancel");

function handleCancel1(reason){
    console.log("handleCancel1", "取消原因:", reason, isCancel(reason));
}
function handleCancel2(reason){
    console.log("handleCancel2", "取消原因:", reason, isCancel(reason));
}

const {token, cancel} = CancelToken.source();
token.subscribe(handleCancel1); // 订阅
token.subscribe(handleCancel2); // 订阅
token.unsubscribe(handleCancel2) // 取消订阅

cancel("测试取消!"); // 取消令牌

用法2:利用工厂构造令牌,且基于“Promise”的API

代码语言:javascript
复制
const CancelToken = require("./CancelToken");
const isCancel = require("./isCancel");

function handleCancel1(reason){
    console.log("handleCancel1", "取消原因:", reason, isCancel(reason));
}
function handleCancel2(reason){
    console.log("handleCancel2", "取消原因:", reason, isCancel(reason));
}

const {token, cancel} = CancelToken.source();
token.promise.then(handleCancel1); // 订阅
const p = token.promise.then(handleCancel2); // 订阅
p.cancel(); // 取消订阅

cancel("测试取消!"); // 取消令牌

用法3:不使用工厂构造令牌

代码语言:javascript
复制
const CancelToken = require("./CancelToken");
const isCancel = require("./isCancel");

function handleCancel1(reason){
    console.log("handleCancel1", "取消原因:", reason, isCancel(reason));
}
function handleCancel2(reason){
    console.log("handleCancel2", "取消原因:", reason, isCancel(reason));
}

let cancel;
const token = new CancelToken((c)=>{
    cancel = c;
});
token.subscribe(handleCancel1); // 订阅
token.subscribe(handleCancel2); // 订阅
token.unsubscribe(handleCancel2) // 取消订阅

cancel("测试取消!"); // 取消令牌

注意事项:在已取消的令牌上订阅的事件,会立即触发。

代码语言:javascript
复制
const CancelToken = require("./CancelToken");

const {token, cancel} = CancelToken.source();
console.log(new Date().toLocaleTimeString(), "[未取消]:订阅(取消事件1); 并将于5秒后,执行取消;");
token.subscribe((reason)=>{
    console.log(new Date().toLocaleTimeString(), "[已取消]:触发(取消事件1)(取消原因:"+reason+"); 并将于5秒后, 在已取消前提下, 订阅(取消事件2);");
    setTimeout(()=>{
        console.log(new Date().toLocaleTimeString(), "[已取消]:订阅(取消事件2);");
        token.subscribe((reason)=>{
            console.log(new Date().toLocaleTimeString(), "[已取消]:触发(取消事件2);");
        });
    }, 5000)
});

setTimeout(()=>{
    console.log(new Date().toLocaleTimeString(), "[未取消]:取消(取消原因:测试取消)");
    cancel("测试取消!");
}, 5000)

3.3. 原理分析(CancelToken.js)

4. Axios 内部如何与 CancelToken 结合?

通过分析 CancelToken 的原理,

Axios 接收到外部传入的 CancelToken 令牌对象后,

只需要订阅令牌的取消事件,

并在取消事件被触发时,作出相应处理即可

订阅:

取消订阅:

5. Axios 与 Fetch API 的 AbortController?

FetchAPI 的 AbortController 可以粗略的理解为 W3C 官方提供的 CancelToken。

Axios 内部也提供了对 AbortController 的兼容处理:

参考:

https://github.com/axios/axios https://axios-http.com/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebJ2EE 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档