前言
在一个vue项目开发的过程中,遇到一个需要中断文件上传的需求,当我利用axios的cancel token实现中断请求的功能之后,想要再次发送post请求,却发现axios直接返回了reject。
axios中关于cancel token的文档
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实现取消请求的步骤:
// 1.利用axios.CancelToken.source()方法生成一个source对象
// (source对象下有一个cancel方法和一个token对象)
// 2.在请求的config中,将source.token赋值给config的cancelToken属性
// 3.发送请求之后,若要取消请求,则执行sourced对象的cancel方法
我的实现方案
getData.js 统一封装的请求接口
// fileObj: 文件对象
// source: axios.CancelToken.source()方法生成的source对象
upload(fileObj, source) {
const formData = new FormData()
formData.append('file', fileObj)
return server.post(url, formData, {
timeout: 9999999, //防止超时
cancelToken: source.token //用surce.token标记请求
})
}
--------------------------------------------------------
upload.vue 上传文件的组件
import axios from 'axios'
export default {
data() {
const source = axios.CancelToken.source()
return{
source, // 将source保存在data中
fileObj: '' //文件对象
}
},
methods:{
// 上传文件
async upload(){
let res = null
try {
res = await this.$api.upload(this.fileObj, this.source)
} catch (e) {
console.log(e.message)
}
},
// 中断上传
cancelReauest() {
this.source.cancel('stop')
}
}
}
问题复现
- 当我执行
upload
方法时,文件能够正常上传 - 点击中断按钮,执行
cancelReauest
方法,文件上传中断,控制台打印错误信息stop
- 再次上传文件,执行
upload
方法时,请求却直接中断,错误被catch捕获,控制台打印错误信息stop
按照我的理解,此时我并没有去执行cancelReauest
方法,文件应该是正常上传才对,但此时请求却直接中断,不太能理解,搜索完谷歌和百度之后也没有类似的问题和解决方案,所以只能自己摸索
猜测及理解
在执行cancelReauest
方法之前,我打印了source
对象,查看了它的数据结构,发现他token
下有一个promise
对象,此时它的状态是pending
当我执行完cancelReauest
方法之后,此时promise
的状态变成了fulfilled
,并且多了一个reason
对象,里面放着我上次停止文件上传传递的信息stop
于是我大胆猜测,文件上传的中断,是根据source.token
下promise
的状态进行控制的
- 当状态为
pending
时,可以正常上传文件 - 当状态为
fulfilled
时,文件上传中断
而在我的代码中,文件上传中断之后
- 存储在
data
中的source
对象,它token
里的promise
状态已经修改为fulfilled
- 当我再次发送请求,
config
中携带的是状态为fulfilled
的source
对象,所有请求直接中断
为了验证我的猜想,我在文件上传中断之后,重新给source
对象赋值,刷新他的promise
状态
cancelReauest() {
this.source.cancel('stop')
this.source = axios.CancelToken.source() //重新赋值
}
修改完毕之后,当我再次发送请求,成功上传!
问题解决,完结撒花!