美文网首页VUE-全技术栈HTTP
vue axios最全拦截器封装 请求头配置 异常状态统一处理

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

作者: 爱学习的小仙女早睡早起 | 来源:发表于2021-08-17 10:49 被阅读0次

    注意点:不要直接对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文件所有方法,在调用时就不需要逐个引入啦

    相关文章

      网友评论

        本文标题:vue axios最全拦截器封装 请求头配置 异常状态统一处理

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