START
- 仅以此文,纪念这个离谱的bug,o(╥﹏╥)o
问题
- 长话短说,使用axios进行请求,浏览器f12检查,请求成功。但是代码逻辑还是进入axios的catch模块。
原因
-
当axios请求完成后走的时then的代码块,如果then代码块中存在错误代码信息,这时就会进入catch中抛出异常(注意:此时控制台并不会报错,因为错误被catch捕获了)
-
axios是异步发起,若发起后页面刷新,那么就会丢失当前进程,导致接收不到。例如 form表单,点击按钮提交后,表单会刷新
特殊情况
- 上述两种原因,结合自身代码,基本上就可以找到问题并解决了,但是还有一种特殊情况,听我细细道来。
踩坑记录
-
长话短说,使用axios进行请求音频二进制数据流,浏览器f12检查,请求成功。但是代码逻辑还是进入axios的catch模块。
效果见下图:
- 猜测一:是不是请求代码写的有问题?
- 一开始我就检查自己的代码,是不是请求代码写的有问题。经过检查,别的请求都是没有问题的,请求都成功也不会进入catch模块。 唯独我这接口请求成功,还是进catch(pass)
- 猜测二:是不是 .then 代码块中存在错误代码
- .then 中就一个 console.log() (pass)
- 猜测三:是不是页面刷新了
- 经过很仔细的检查判断,不存在表单,不存在页面刷新。(pass)
- 猜测四:是不是请求二进制数据流没有添加响应类型
- 添加了
responseType:'blob'
,但是还是会进入catch (pass)
- 添加了
解决方案
-
由于项目是同事封装的axios
-
在axios中 添加了响应拦截器
- 代码如下
axios.interceptors.response.use( response => { if (res.code !== 'ok') { if (response.headers['content-type'].search('octet-stream') > -1) { return response; } Message({ message: res.message || 'Error', type: 'error', duration: 4 * 1000 }); return Promise.reject(new Error(res.message || 'Error')); } else { return response; } }
解释一下:经过排查,同事axios会判断返回的 res数据 是否包含 code === ‘ok’
若包含,则会返回resolve() (进入 .then)
若不包含。则会进入上述if 语句
因为二进制数据流,直接返回的就是二进制数据流,不包含res.code。所以会进入 上面代码的if
if (response.headers[‘content-type’].search(‘octet-stream’) > -1) {
return response;
}这句话会判断后端返回的http中的header : ‘content-type’ 信息 ,是否包含特殊标识,包含则不进入catch,不包含则进入。
解决方案:
- 后端添加 content-type