关于请求中断的一些学习

855 阅读4分钟

熟悉公司项目,摸索到 axios 的封装的时候,发现了一些以前没接触过的东西 。

1. 使用场景

大致的场景是,有一个下拉框,点击不同的选项会向服务器发送同一个请求但携带不同的参数,响应回来的数据在一个折线图里面展示,然后我就发现了 cancelToken 这个小东西。

项目里面取消的是上一次的请求,擦,前人写的代码还蛮有意思的,上面需求实现的思路是,给下拉框双向绑定一个值,然后监听这个值,变化了就发送请求,然后如果当前请求还没完成,用户又发送一个新的请求,就取消上次请求,保证数据是用户想要的最新的。

2. cancelToken

首先介绍一下 cancelToken,在官网的文档中给了两个栗子,我给大概说明一下

2.1 使用 source 函数

const CancelToken = axios.CancelToken;
const source = CancelToken.source();
​
axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
     // 处理错误
  }
});
​
axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})
​
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

axios 实例上边会有 CancelToken 属性,该属性会有一个 source 方法,该方法返回一个对象,上边代码定义为了 source。在请求中,第二个参数中的 cancelToken 字段用 source.token 标记,这样你执行 source.cancel 方法的时候,被标记的请求就取消了。所以上边的 postget 请求都会取消。

2.2 使用 CancelToken 构造函数

const CancelToken = axios.CancelToken;
let cancel;
​
axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  })
});
​
// cancel the request
cancel();

通过传递一个 executor 的函数给 axios.CancelToken 的构造函数,executor 就能接收到一个参数,这个参数是一个函数,执行他就能终止请求。

2.3 和防抖的区别

按照我的理解,实现的目的都是差不多的吧,都有防止请求数据混淆冲突,取消重复请求,保证数据最新,提高性能的特点,不同的是应用场景的不同。防抖都知道最经典的就是提交按钮,给下拉框写防抖说实话,不太好写吧。防抖也可以用 cancelToken 来中断请求。

3. XMLHttpRequest

也是看大佬们的博客和大家的讨论才知道,ajax不算是一种技术或者工具,是能说是一种概念,技术方案,特点就是能够局部刷新页面,其中的重点就是 XMLHttpRequest 原生的是这么用的

xhr = new XMLHttpRequest();
xhr.open("GET","url",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.onreadystatechange = function(){
    //请求成功时
    if(xhr.readyState == 4 && xhr.status == 200){
        alert(xhr.responseText);
    }
}
xhr.send('参数');

readyState 存有 XMLHttpRequest 的状态,0~4

  • 请求未初始化
  • 服务器连接已经建立
  • 请求已接受
  • 请求处理中
  • 请求已完成,且响应已就绪。

status 就和 http 协议的状态码一样,

使用起来还是比较繁琐的,我反正是没有用过, axios 是二次封装后基于 promise 的网络请求库,浏览器环境和 Node 环境都可以使用,在Node 环境是基于 http 模块,浏览器环境就基于 XMLHttpRequest 了。axios 的使用就简单多了

4. fetch

const url = "http://example.com/";
const options = {
  method: "POST",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json;charset=UTF-8",
  },
  body: JSON.stringify({
    a: 10,
    b: 20,
  }),
};
​
fetch(url, options).then((response) => {
  console.log(response.status);
});
​

更加简单就是

fetch(url).then(...).catch(...)

fetch 是浏览器自带的,是原生的,拿它和 axios 比较不大合适,应该拿它和 xhr 做比较(偷笑),这样一比较,fetch 可就强多了,支持promise,对 request 和 response 也进行了抽象。然后 fetch 优势就是是浏览器原生支持的,劣势可能就是压不过 axios 这个地头蛇,霸占网络请求多年,一时间比较撼动地位,再加上 fetch 出现的时间比较短,暂时还没有比较成熟的库对它进行封装。

5. 总结

axios 的 cancelToken 有两种方式,用来中断请求。axios.isCancel 方法可以判断是不是请求中断导致的请求异常

ajax 是异步请求的统称,XMLHttpRequest 和 fetch 都是原生请求对象,axios 是基于 XMLHttpRequest 的封装,fetch 和 axios 都支持 Promise.