最强axios封装之函数式封装

1,091 阅读4分钟

一、常规引入

import axios from 'axios'; 
import api from '../apis';  //引入接口
import qs from 'qs';
import store from '@/store';
import storage from 'store';
import notification from '@.../notification';  //引入ui组件库里的组件
import message from '@.../es/message'; //引入ui组件库里的组件
import { ACCESS_TOKEN, ACCESS_ID } from '@/scripts/map'; //引入token
import { codeMessage } from '@/scripts/map';   //引入code状态文件
import { labelReplaceExp } from '@/scripts/regexp';    //引入花括号正则

二、封装函数

1、创建axios实例

function create (url) {
 let baseURL = '';
 if (url.indexOf('npo-workflow') !== -1) {
  baseURL = process.env.VUE_APP_BASE_URL_WORK;
 } else {
  baseURL = process.env.VUE_APP_BASE_URL;
 }
 return axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: baseURL,
  // 超时
  timeout: 10000,
 });
}

该函数可根据不同的接口动态的修改baseUrl,满足单个项目的接口有多个baseUrl的需求

2、异常拦截处理器函数

function errorHandler (error) {
 if (error.response) {
  const { data, status } = error.response;
  const text = data && data.text;
  // 从 localstorage 获取 token
  const token = storage.get(ACCESS_TOKEN);
  console.log(data, text, status, 'errorHandler');
  if (status === 401 && token) {
   setTimeout((_) => {
    window.location.reload();
   }, 1500);
  } else if (text) {
   notification.destroy();
   // 有出错信息才提示
   notification.error({
    message: codeMessage[status],
    description: text,
   });

3、拦截器函数

function interceptors (instance) {
 // request拦截器
 instance.interceptors.request.use(
  (config) => {
   const token = storage.get(ACCESS_TOKEN);
   // 如果 token 存在
   // 让每个请求携带自定义 token 请根据实际情况自行修改
   if (token) {
    config.headers[ACCESS_TOKEN] = token;
   }
   return config;
  },
  (e) => {
  //报错异常调用异常拦截处理器函数
   errorHandler(e);
  },
 );

 // 响应拦截器
 instance.interceptors.response.use(
  (res) => {
   const { data, status } = res;
   const _data = data && data.data;
   const _code = data && data.code;
   const success = _code === 0; // 判断业务是否正常
   //获取data
   if (data && success) {
    return _data ? _data : ((_data === undefined || _data === null) && {}) || _data;
   }
  },
  (e) => {
   errorHandler(e);
  },
 );
}

4、axios请求参数处理函数

function buildConf(conf) {
  return Object.assign(
    {
      method: "GET",
      responseType: "json",
      withCredentials: true,
    },
    conf
  );
}

该函数把要请求的url, urlparams, params参数和基础参数合并用于请求

5、axios请求处理函数

function run(conf) {
  if (conf.url.indexOf("{") !== -1 && conf.urlparams) {
    // 替换url的关键参数urlparams,用于在url苹姐参数的情况
    conf.url = conf.url.replace(labelReplaceExp, function (label, key) {
      let re = conf.urlparams[key];
      delete conf.urlparams[key];
      return re;
    });
  }
  // 创建实例instance
  let instance = create(conf.url);
  conf = Object.assign({}, conf);
  // 实例调用拦截器函数
  interceptors(instance, conf);
  return instance(conf);
}

三、get、post、put等函数封装

/**
 * Get 形式获取数据
 * @param  {String}   url         请求地址
 * @param  {Object}   urlparams   请求参数
 * @param  {Object}   params      请求数据
 * @return {Object}               Promise 对象
 */
function get(url, urlparams, params) {
  if (urlparams && !params) {
    params = urlparams;
    urlparams = null;
  }
  if (url) {
    url = api[url] || url;
  }
  return run(buildConf({ url, urlparams, params }));
}

/**
 * Post 形式获取数据
 * @param  {String}   url         请求地址
 * @param  {Object}   urlparams   请求参数
 * @param  {Object}   data        请求数据
 * @return {Object}               Promise 对象
 */
function post(url, urlparams, data) {
  if (urlparams && !data) {
    data = urlparams;
    urlparams = null;
  }
  if (url) {
    url = api[url] || url;
  }
  return run(buildConf({ method: "post", url, urlparams, data }));
}

/**
 * Put 形式更新数据
 * @param  {String}   url         请求地址
 * @param  {Object}   urlparams   请求参数
 * @param  {Object}   data        请求数据
 * @return {Object}               Promise 对象
 */
function put(url, urlparams, data) {
  if (urlparams && !data) {
    data = urlparams;
    urlparams = null;
  }
  if (url) {
    url = api[url] || url;
  }
  return run(buildConf({ method: "put", url, urlparams, data }));
}

四、导出

const request = {
  get,
  post,
  put,
};
const system = {
  request,
};
export default system;

五、完整代码

import axios from "axios";
import api from "../apis"; //引入接口
import qs from "qs";
import store from "@/store";
import storage from "store";
import notification from "... /notification";
import message from "... /message";
import { ACCESS_TOKEN, ACCESS_ID } from "@/scripts/map"; //引入token
import { codeMessage } from "@/scripts/map";
import { labelReplaceExp } from "@/scripts/regexp"; //引入花括号正则
import router from "@/router";

// 创建axios实例
function create(url) {
  let baseURL = "";
  if (url.indexOf("npo-workflow") !== -1) {
    baseURL = process.env.VUE_APP_BASE_URL_WORK;
  } else {
    baseURL = process.env.VUE_APP_BASE_URL;
  }
  return axios.create({
    // axios中请求配置有baseURL选项,表示请求URL公共部分
    baseURL: baseURL,
    // 超时
    timeout: 10000,
  });
}
// 异常拦截处理器
function errorHandler(error) {
  if (error.response) {
    const { data, status } = error.response;
    const text = data && data.text;
    // 从 localstorage 获取 token
    const token = storage.get(ACCESS_TOKEN);
    console.log(data, text, status, "errorHandler");
    if (status === 401 && token) {
      // store.dispatch('Logout').then(() => {
      //   setTimeout(() => {
      //     window.location.reload();
      //   }, 1500);
      // });
      // storage.remove(ACCESS_TOKEN);
      // storage.remove(ACCESS_ID);
      setTimeout((_) => {
        window.location.reload();
      }, 1500);
    } else if (text) {
      notification.destroy();
      // 有出错信息才提示
      notification.error({
        message: codeMessage[status],
        description: text,
      });
      // console.log(status, text);
      if (text === "未登陆") {
        message.destroy();
        message.warn(`${text},请先进行登陆!`);
        storage.remove(ACCESS_TOKEN);
        storage.remove(ACCESS_ID);
        // setTimeout(_ => {
        //   router.replace('/');
        // }, 1500);
        setTimeout((_) => {
          window.location.reload();
        }, 3000);
        // 跳转到登录页面
        // setTimeout(_ => {
        //  if (location.href.indexOf('10.33.122.52:8070') !== -1) {
        //   window.location.href = '/portal-admin/#/sign-in/login?source=1';
        //  } else if (location.href.indexOf('noc.gdgov.cn') !== -1) {
        //    window.location.href = '/portal-admin/#/sign-in/login?source=1';
        //  } else {
        //    window.location.href = '/npo-portal/portal-admin/#/sign-in/login?source=1';
        //  }
        // }, 1500);
      }
      // store.dispatch('closeLoading');
    }
  }
  return Promise.reject(error);
}
function interceptors(instance, conf) {
  // request拦截器
  instance.interceptors.request.use(
    (config) => {
      const token = storage.get(ACCESS_TOKEN);
      // 如果 token 存在
      // 让每个请求携带自定义 token 请根据实际情况自行修改
      if (token) {
        config.headers[ACCESS_TOKEN] = token;
      }
      return config;
    },
    (e) => {
      errorHandler(e);
    }
  );

  // 响应拦截器
  instance.interceptors.response.use(
    (res) => {
      const { data, status } = res;
      const _data = data && data.data;
      const _code = data && data.code;
      const success = _code === 0; // 判断业务是否正常
      if (data && success) {
        return _data ? _data : ((_data === undefined || _data === null) && {}) || _data;
      }
    },
    (e) => {
      errorHandler(e);
    }
  );
}

function run(conf) {
  if (conf.url.indexOf("{") !== -1 && conf.urlparams) {
    // 替换关键参数
    conf.url = conf.url.replace(labelReplaceExp, function (label, key) {
      let re = conf.urlparams[key];
      delete conf.urlparams[key];
      return re;
    });
  }
  // 创建实例instance
  let instance = create(conf.url);
  conf = Object.assign({}, conf);
  // 实例调用拦截器函数
  interceptors(instance, conf);
  return instance(conf);
}
function buildConf(conf) {
  return Object.assign(
    {
      method: "GET",
      responseType: "json",
      withCredentials: true,
    },
    conf
  );
}

/**
 * Get 形式获取数据
 * @param  {String}   url         请求地址
 * @param  {Object}   urlparams   请求参数
 * @param  {Object}   params      请求数据
 * @return {Object}               Promise 对象
 */
function get(url, urlparams, params) {
  if (urlparams && !params) {
    params = urlparams;
    urlparams = null;
  }
  if (url) {
    url = api[url] || url;
  }
  return run(buildConf({ url, urlparams, params }));
}

/**
 * Post 形式获取数据
 * @param  {String}   url         请求地址
 * @param  {Object}   urlparams   请求参数
 * @param  {Object}   data        请求数据
 * @return {Object}               Promise 对象
 */
function post(url, urlparams, data) {
  if (urlparams && !data) {
    data = urlparams;
    urlparams = null;
  }
  if (url) {
    url = api[url] || url;
  }
  return run(buildConf({ method: "post", url, urlparams, data }));
}

/**
 * Put 形式更新数据
 * @param  {String}   url         请求地址
 * @param  {Object}   urlparams   请求参数
 * @param  {Object}   data        请求数据
 * @return {Object}               Promise 对象
 */
function put(url, urlparams, data) {
  if (urlparams && !data) {
    data = urlparams;
    urlparams = null;
  }
  if (url) {
    url = api[url] || url;
  }
  return run(buildConf({ method: "put", url, urlparams, data }));
}
const request = {
  get,
  post,
  put,
};
const system = {
  request,
};
export default system;

六、接口代码api.js与接口请求

const api = {
  userKey:'/user?key={key}&val={val}',
  user:'/user'
}

因为合理的封装,可以比较简洁的进行请求

async getUser(){
  const result = await this.system.request.get('userKey',{key:1,val:2},{a:1});
}