Bootstrap

vue axios请求成功进入catch原因

START

  • 仅以此文,纪念这个离谱的bug,o(╥﹏╥)o

问题

  • 长话短说,使用axios进行请求,浏览器f12检查,请求成功。但是代码逻辑还是进入axios的catch模块。

原因

  1. 当axios请求完成后走的时then的代码块,如果then代码块中存在错误代码信息,这时就会进入catch中抛出异常(注意:此时控制台并不会报错,因为错误被catch捕获了)

  2. axios是异步发起,若发起后页面刷新,那么就会丢失当前进程,导致接收不到。例如 form表单,点击按钮提交后,表单会刷新

特殊情况

  • 上述两种原因,结合自身代码,基本上就可以找到问题并解决了,但是还有一种特殊情况,听我细细道来。

踩坑记录

  1. 长话短说,使用axios进行请求音频二进制数据流,浏览器f12检查,请求成功。但是代码逻辑还是进入axios的catch模块。

    效果见下图:

    blob数据.png

  • 猜测一:是不是请求代码写的有问题?
    • 一开始我就检查自己的代码,是不是请求代码写的有问题。经过检查,别的请求都是没有问题的,请求都成功也不会进入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
;