详解axios拦截器,同步判断mock模式与开发模式

前言:最近做项目

一、index文件

封装了两套,一套返回json,一套返回form

基础的一些封装get,post,put,delete一些方法,如果有额外需求,可以自定义添加

/* eslint-disable */
// import router from 'src/router'
import axios from 'axios';
import Qs from 'qs';
import userInterceptor from './userInterceptors';

// form 请求
const instanceForm = axios.create({
  baseURL: '',
  timeout: 100000,
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
  },
  withCredentials: true,
  transformRequest: [
    data => {
      let dataIn = data;
      dataIn = Qs.stringify(dataIn);
      return dataIn;
    },
  ],
});

// json

const instance = axios.create({
  baseURL: '',
  timeout: 100000,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
  withCredentials: true,
  transformRequest: [data => JSON.stringify(data)],
});

// 全局 axios原型加入 拦截
userInterceptor([instance, instanceForm, axios]);

export { instanceForm };

// 对 get set 做一层封装 比较常用的事 get set 如果其他用得上的再自行封装
export function Get(url, data) {
  return instance.get(url, {
    params: data,
  });
}

export function Post(url, data) {
  return instance.post(url, data);
}

export function Put(url, data) {
  return instance.put(url, data);
}

export function Delete(url, data) {
  return instance.delete(url, {
    data,
  });
}

// 相关restful 接口封装
export function initModule(prefix, reqObj) {
  // prefix 内部引用
  let obj = {};
  const { get = [], post = [], put = [], deletes = [] } = reqObj;
  const geneApi = function(api, transMethod) {
    api.forEach(ele => {
      if (!obj[ele]) {
        obj[ele] = function(param) {
          return transMethod(`${prefix}${ele}`, param);
        };
      }
    });
  };
  geneApi(get, Get);
  geneApi(post, Post);
  geneApi(put, Put);
  geneApi(deletes, Delete);

  return obj;
}
export default instance;

二、userInterceptors文件

axios原型全局加入拦截的配置文件

import catchError from './catchError';  
import responseHandle from './response';    
import configInter from './configInter';   

export default function(insArray) {
  const insArrayIn = insArray;
  if (insArrayIn.length) {
    for (let i = 0; i < insArray.length; i++) {
      // request 拦截
      insArrayIn[i].interceptors.request.use(configInter, catchError);  //不是mock模式可以注释
      // response 拦截 axios 相关 response 返回需要注意一些细节
      insArrayIn[i].interceptors.response.use(responseHandle, catchError);
    }
  }
}

三、configInter文件

加入了mock数据环境(配置.env.development,.env.mocking,.env.production文件)
VUE_APP_MOCKING = no
同时本地代理取消,打包后暴露出config文件,交给运维人员配置
备注:(如不引入mock数据,可不配置此文件)

/**
 * 将所有的代理config从文件中 独立出来方便运维人员配置
 */
import get from 'lodash/get';
import { getToken } from '@/utils/auth';

export default function(config) {
  //解决token问题
  if (config.headers.common['Authorization']) {
    let token = config.headers.common['Authorization'].slice(7)
    if (token !== getToken()) {
      location.reload()
    }
  }
  const FLAG = window.__HTTP_FLAG__;

  if (window[FLAG]) {
    const configOut = window[FLAG];
    const url = get(config, 'url');
    // 拦截 非mock环境下(如无需暴露config文件,上面代码可无视)
    if (process.env.VUE_APP_MOCKING !== 'yes') {
      Object.keys(configOut).forEach(prefix => {
        const host = configOut[prefix];
        const re = new RegExp(`^${prefix}`, 'ig');
        if (re.test(url)) {
          config.url = host + url;
        }
      });
    }
  }
  return config;
}

四、response文件

通用情况下的拦截,同时过滤了一些特殊情况(如无code码,二进制流的情况),添加了拦截白名单

import get from 'lodash/get';
import { Message } from 'element-ui';
import whiteUrl from './resWhite'; 

export const SUC_CODE = '0'; // 成功
export const FAIL_CODE = '1'; // 失败

export default function(res) {
  // response 封装
  const code = get(res, 'data.code', false);
  const mes = get(res, 'data.message', '无返回信息'); // 默认值 可以用 config配置
  const url = get(res, 'config.url', false);
  const result = get(res, 'data.result', 'noResult');
  const headers = get(res, 'headers', {});

  if (res.status === 200) {
    // 加入白名单过滤掉 下拉公共接口
    if (!code) {
      // 流处理
      if (headers['content-disposition']) {
        return get(res, 'data', null);
      }
      // 查看result属性 为什么不写 code码?????
      if (result === false) {
        return res.data;
      }
      // 二维码
      if (/\/cloud-oauth-service\/verifyCode$/gi.test(url)) {
        return res.data;
      }

      let isWhite = false;
      whiteUrl.forEach(i => {
        if (i(url)) {
          isWhite = true;
        }
      });
      if (isWhite) {
        return {
          code: '0',
          datas: res.data,
        };
      } else {
        Message.warning({
          message: `${url} => ${mes}`,
        });
        return;
      }
    }
    if ((code === '201' || code === '202') && mes) {
      Message.error({
        message: get(res, 'data.detail', '无返回信息'),
      });
    }

    if (code === FAIL_CODE) {
      Message.error({
        message: mes,
      });
      return res.data;
    }
  } else {
    if (mes) {
      Message.warning({
        message: mes,
      });
    }
    return;
  }
  return res.data;
}

大概完结吧,可能后期会加入白名单功能。。。


版权声明:本文为weixin_39884801原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。