vue axios最全拦截器封装 请求头配置 异常状态统一处理 loading设置

注意点:不要直接对axios原型设置拦截,先创建axios实例: axios.create
然后分别用到:
service.interceptors.request.use
service.interceptors.response.use

拦截器代码:

import axios from  axios ;
import router from  ../router ;
import db from  @/utils/localstorage ;
import { MessageBox, Message, Loading } from  element-ui ;
import store from  @/store ;
import { getToken } from  @/utils/auth ;
var aaa = 0
let nowUrl =   ;

// 创建axios实例
const service = axios.create({
  // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // 跨域请求时发送cookie
  baseURL: config.BASE_API,
  timeout: 30000 // 请求超时
});

// 请求拦截器
let loadingInstance = null;
service.interceptors.request.use(
  (config) => {
    nowUrl = config.url;
    // do something before request is sent
   
    var xtoken = localStorage.getItem( loginToken );
    config.headers[ tenantPath ] = (window.location.pathname.split( / )[1] ===  sdm  ? window.location.pathname.split( / )[2] : window.location.pathname.split( / )[1]) ||   ;
    config.headers[ t ] = store.getters.t;
    if (xtoken != null) {
      config.headers[ X-User ] = getToken();
      config.headers[ System ] =  M ;
      config.headers[ crmversion ] =  V1.0.0 ;
      config.headers[ channel ] =  PC ;
      config.headers[ Content-Type ] =  application/json ;
    }
  
    if (config.responseType ===  blob ) {  // blob类型 延长超时时间
      config.timeout = 60000;
      loadingInstance = Loading.service({
        lock: true,
        text:  Loading ,
        spinner:  el-icon-loading ,
        background:  rgba(0, 0, 0, 0.7) 
      });
    }
    if (config.url.includes( add ) || config.url.includes( edit ) || config.url.includes( update ) || config.url.includes( create )) {
      loadingInstance = Loading.service({
        lock: true,
        text:  Loading ,
        spinner:  el-icon-loading ,
        background:  rgba(0, 0, 0, 0.7) 
      });
    }
    if (config.url.indexOf( entrust/query/pagination )) {
      config.timeout = 300000;
    }
    if (config.url.includes( /member/import ) || config.url.includes( /dataSetRoler/import )) { // 导入文件设置请求头
      config.headers[ Content-Type ] =  multipart/form-data ;
    }
    return config;
  },
  (error) => {
    // 处理请求错误
    console.log(error); // for debug
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  /**
   * 如果您想获得http信息,例如头信息或状态信息
   * 请返回 response => response
   */

  /**
   * 通过自定义代码确定请求状态
   * 这里只是一个例子
   * 还可以通过HTTP状态代码来判断状态
   */
  (response) => {
    if (response.config.responseType ===  blob ) {  // 下载时直接return 返回blob
      loadingInstance && loadingInstance.close();
      return response.data;
    }
    if (response.config.url.includes( add ) || response.config.url.includes( edit ) || response.config.url.includes( update ) || response.config.url.includes( create )) {
      loadingInstance && loadingInstance.close();
    }
    const res = response.data;
    // 如果状态码不是0,则判断为错误。
    if (res.status !== 0 && res.status !== 200) {
      if (res.status ==  400 ) {
        Message.closeAll(); // 关闭之前的弹出信息
        Message({
          dangerouslyUseHTMLString: true,
          message: res.message ||  Error ,
          type:  error ,
          duration: 5 * 1000
        });
      }

      // 50008: 非法的令牌; 50012: 其他客户端登录; 50014: 令牌过期;
      if (res.code === 401 || res.code === 50012 || res.code === 50014) {
        // 重新登陆
        MessageBox.confirm( 很抱歉,登录已过期,请重新登录 , {
          confirmButtonText:  重新登录 ,
          cancelButtonText:  撤销 ,
          type:  warning 
        }).then(() => {
          store.dispatch( user/resetToken ).then(() => {
            location.reload();
          });
        });
      }
      return Promise.reject(res);
    } else {
      return res;
    }
  },
  (error) => {
    console.log( err  + error.request.response); // for debug
    if (!error.request.response) {
      Message({
        message:  服务连接失败 ,
        type:  error ,
        duration: 5 * 1000
      });
      return Promise.reject(error);
    }
    const err = JSON.parse(error.request.response);
    loadingInstance && loadingInstance.close();
    if (nowUrl.indexOf( /menu/getList ) !=  -1 ) {
      return Promise.reject(error);
    } 
    if (error.request &&
      error.request.response &&
      JSON.parse(error.request.response) &&
      JSON.parse(error.request.response).status === 600 &&
      JSON.parse(error.request.response).message) {
      return Promise.reject(error);
    }
    if (err.status === 401 && nowUrl.indexOf( /menu/getList ) ==  -1 ) {
      // 重新登陆
      if (aaa == 0) {
        aaa++
        MessageBox.confirm( 很抱歉,登录已过期,请重新登录 , {
          confirmButtonText:  重新登录 ,
          showCancelButton: false,
          type:  warning 
        }).then(() => {
          db.remove( router )
          db.remove( loginToken )
          aaa = 0
          router.push({ path:  /login  });
        });
      }
      return Promise.reject(error);
    }
   
    if (
      error.request &&
      error.request.response &&
      JSON.parse(error.request.response) &&
      JSON.parse(error.request.response).status == 400 &&
      JSON.parse(error.request.response).message
    ) {
      Message({
        message: JSON.parse(error.request.response).message,
        type:  error ,
        duration: 5 * 1000
      });
      return Promise.reject(error);
    }
    if (error.message.indexOf( timeout ) !== -1) {
      Message({
        message:  请检查网络后重试 ,
        type:  error ,
        duration: 5 * 1000
      });
      return Promise.reject(error);
    } else {
      Message({
        message: JSON.parse(error.request.response).message,
        type:  error ,
        duration: 5 * 1000
      });
      return Promise.reject(error);
    }
  }
);

export default service;

上面我们对响应状态 401 500 其他等状态的错误处理封装的很详细,以及code异常时的提示都做了处理;
在调用时不需要再处理 异常status 或者异常code 的情况,小心页面上发生两次错误提示哈!

注意上面是 export default service; 有default, 所以我们在api文件里引用时 import request from @/utils/request ,这里的request可以是任何自定义的名称~

调用接口代码:manage.js

import request from  @/utils/request 
const prefix =  web 

export function getKey() {
  return request({
    url: prefix +  /member/ldap/getKey ,
    method:  get 
  });
}

export function getValidCode(data) {
  return request({
    url: prefix +  /captcha ,
    method:  get ,
    data
  });
}

封装到上面的程度后,每次调用接口时需要 把manage.js 里的方法一个个import进来,超级不方便
可以看我下篇笔记,只需要一步一次输出manage.js文件所有方法,在调用时就不需要逐个引入啦

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容