前言
做一个Vue的项目时,遇到频繁切换标签的问题。由于不同标签请求的ajax的结果所需时间不同,点击不同标签时,响应时间最慢的数据会覆盖之前响应的数据,显示数据跟所点击标签不对应。当时为了处理这个问题,没想到好方法,只好控制在点击下一个标签前,必须等前一个标签的结果回来之后进行。
后来做API的统一管理时,看到前人写的axios的interceptor里有CancelToken这样一个东西,查了查资料,发现这个可以取消请求,踏破铁鞋无觅处,刚好可以用来处理之前遇到的频繁切换标签的问题。今作一记录,也好更好的理解这个功能。
述求
点击标签时,取消之前正在执行的请求,使得切换标签时,页面得到的是最后请求的结果,而不是响应最慢的结果。
用法
官方案例
- 使用 CancelToken.source 工厂方法创建 cancel token,像这样:
// CancelToken是一个构造函数,用于创建一个cancelToken实例对象 // cancelToken实例对象包含了一个promise属性,值为可以触发取消请求的一个promise const CancelToken = axios.CancelToken; // 执行source()得到的是一个包含了cancelToken对象和一个取消函数cancel()的对象 // 即 source = {token: cancelToken对象, cancel: 取消函数} const source = CancelToken.source(); // 在请求的配置中配置cancelToken,那么这个请求就有了可以取消请求的功能 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.');
- 通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token
const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // executor 函数接收一个 cancel 函数作为参数 // 把cancel函数传递给外面,使得外面能控制执行取消请求 cancel = c; }) }); // cancel the request cancel();
看起来有些晕,毕竟不知道里面是怎么运作的,稍后通过源码解析。这里简单解释就是,在请求中配置cancelToken
这个属性,是为了使得请求具有可以取消的功能;cancelToken
属性的值是一个CancelToken
实例对象,在它的executor
函数中提取出cancel
函数,执行这个cancel
函数来取消请求。
我的实例
点击标签,执行getCourse
函数。点击某个标签时,先取消之前的请求(如果之前的请求已完成,取消请求不会有任何操作)。效果是,页面显示的总是最后点击的标签对应的结果。
分两步,第一步,在get请求中配置cancelToken
属性,开启取消请求的功能,且在其属性值中将cancel
函数赋给cancelRequest
,使得外部可以调用cancel
函数来取消请求;第二步,在执行请求前,先取消前一次的请求。
import axios from 'axios'
export default {