美文网首页
错误封装axios配置,导致响应出现叠加

错误封装axios配置,导致响应出现叠加

作者: NIGangJun | 来源:发表于2019-07-16 18:32 被阅读0次
    业务需求

    公司有多个项目共同用到了已封装好的axios(funcation http()),基于去掉复制粘贴这种重复工作。

    • 统一封装所有项目axios方法(\color{red}{本文问题重点}
    • 把封装好的方法打包发布到公司npm私服(不涉及)
    问题重现

    Vue项目页面Create(){}的时候调用了一个接口,相当于调用了http()方法,此时响应response还是正常的。
    但是当再调用任何接口的时候,response出现了多次(我在响应拦截器中console了response,调用了几次http(),就多出现几次console)

    // axios 封装的方法(关键代码)
    // httpClient是axios重命名、因为每个项目的baseURL不一样,所以每次需要传一个base进来、url是接口地址
    export default function http(base, url, data = {}, type = "get", header = {}) {
      httpClient.defaults.baseURL = base;
      httpClient.interceptors.response.use(
        response => {
          console.log("response", response);
          return response
        },
        error => {
          console.log("error", error.response);
          if (error.response.status === 401 && error.response.data.code === 'nosso') {
            window.location.href = base + '/redirect/to/frontend?page=' + encodeURIComponent(window.location.href)
          }
          return error.response
        }
      );
      type = type.toLowerCase();
      let promise;
      return new Promise((resolve, reject) => {
        if (type === 'post') {
          promise = httpClient.post(url, data, {headers: header})
        } else if (type === 'put') {
          promise = httpClient.put(url, data, {headers: header})
        } else if (type === 'delete') {
          promise = httpClient.delete(url, {data: data, headers: header})
        } else {
          promise = httpClient.get(url, {params: data, headers: header})
        }
        promise.then(response => {
          resolve(response.data);
        }).catch(error => {
          reject(error)
        })
      })
    }
    
    Create后--正常情况 第一次调用退出方法--错误情况 第二次调用退出方法--错误情况

    如果再点退出,response的数量会继续累加。当时看到这个情况后很不理解。首先能确定的是两个请求格式和参数完全一致,那么问题只能在响应和后端数据上了(排除后台数据问题)。
    百度了一圈,基本没有发现这个问题的解决办法(本来是没有问题的,这个封装的方法最后是由我自己改动的。详细改动:将baseURL和响应拦截器放在了http()里面,就出现以上错误。之所以会放在里面是因为base位置问题,后面细说)。

    为什么会出现这个问题 && 问题原因

    项目以前http()的响应拦截器里的地址是写死的,封装后,需要根据不同的项目给不同的请求前缀地址。而axios默认的请求配置是在发生请求之前定义的。

    原项目axios逻辑顺序

    如图,调用http()的时候,需要将一个base传入baseURL和响应拦截器里面。因为是配置项,有点违背代码逻辑,所以将baseURL和响应拦截器放在http()里面,如下图:

    有问题的axios逻辑顺序

    回到上面的问题,我猜测把响应拦截器放在http()后,因为每次都有个new Promise的过程,相当于在项目里,每调一次http(),axios就多一个响应拦截器配置,每个响应都依次依赖,所以才导致调用一个接口,就多一个response结果。

    解决

    找到问题就好解决,最开始没有想到,httpClient.default.baseURL可以当做axios服务的全局变量。也就是说,我只需要把这个default.baseURL放在http()里面,响应拦截器放在外面就可以了

    httpClient.interceptors.response.use(
      response => {
        return response.data
      },
      error => {
        if (error.response.status === 401 && error.response.data.code === 'nosso') {
          window.location.href = httpClient.defaults.baseURL + '/redirect/to/frontend?page=' + encodeURIComponent(window.location.href)
        }
        return error.response
      }
    );
    /**
     * 封装请求方法
     * @params(url)
     * @params(data)
     * returns { Promise }
     * @user NIGangJun <nigangjun@aeotrade.com>
     */
    export default function http(base, url, data = {}, type = "get", header = {}) {
      httpClient.defaults.baseURL = base;
      type = type.toLowerCase();
      let promise;
      return new Promise((resolve, reject) => {
        if (type === 'post') {
          promise = httpClient.post(url, data, {headers: header})
        } else if (type === 'put') {
          promise = httpClient.put(url, data, {headers: header})
        } else if (type === 'delete') {
          promise = httpClient.delete(url, {data: data, headers: header})
        } else {
          promise = httpClient.get(url, {params: data, headers: header})
        }
        promise.then(response => {
          resolve(response);
        })
      })
    }
    

    就是把响应拦截器放在外面,然后base替换成baseURL就行了。

    有个优化的地方:响应拦截器resolve的数据换成了response.data,reject的数据换成了error.response。promise就直接去掉了catch(如果要catch,响应拦截器中reject的数据要return Promise.reject(error.response),并且http()方法里不能再使用 new Promise封装)

    总结

    虽然最后解决结果很简单,但是中间这个过程不可忽略。

    • axios配置应该符合规范;
    • 查找代码问题应该按照功能进行拆分,依次查询;

    问题千变万化,解决思路如出一辙——用心;

    相关文章

      网友评论

          本文标题:错误封装axios配置,导致响应出现叠加

          本文链接:https://www.haomeiwen.com/subject/eztfkctx.html