记一次实际项目网络请求对axios的封装

198 阅读2分钟

概述

在现在的前端开发当中,如果是工程化项目,多数是基于框架的脚手架进行开发的,因此在数据请求这方便,使用最普遍的就是axios了,axios的好处不仅仅是简化了我们网络请求的代码量,还提供了网络请求拦击,响应拦截等等功能,因此在项目中我们比不可少会使用axios来封装我们自己请求。

实现

import Vue from 'vue';
import Axios from 'axios';
import qs from 'qs';


// axios 实例对象(项目中如果多个接口地址配置不一样,就需要实例化出axios对象,一个接口域名配置一样的话无所谓)
const axios = Axios.create();
//请求超时实现
 axios.defaults.timeout = 60000;
 //接口域名地址:例如https://etextbook.hep.com.cn:50000/UserOnline/Search,baseURL为https://etextbook.hep.com.cn:50000
axios.defaults.baseURL = https://etextbook.hep.com.cn:50000;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
// 请求拦截器
axios.interceptors.request.use(
  async config => {
    // 添加功能请求参数
    let requestData = Vue.prototype.baseRequestData(config);
    //声明验签参数,通过将接口请求参数通过算法加密给后端验签使用(根据自己项目需求来)
    let token = '';
    //当接口返回值类型不是二进制数据(例如不是音视频)
    if (config.responseType !== 'arraybuffer') {
    //js接收返回值的时候,可能会出现大数精度丢失的情况,这里需要处理下
      config.transformResponse = [
        function (data) {
          // 对 data 进行任意转换处理
          const par = /([^\\]{1}[":]{2}[ \[]{0,2})([\d]{16,})([\r\n},\]]{1})/g;
          let responseText = data;
          const arrReg = /\[((\d,)*\d)*\]/g;
          responseText = responseText.replace(arrReg, match => {
            if (match.length > 2) {
              return (
                match.charAt(0) +
                match.slice(1, match.length - 1).replace(/([\d]{16,})/g, '"$1"') +
                match.charAt(match.length - 1)
              );
            } else {
              return match;
            }
          });
          responseText = responseText.replace(par, '$1"$2"$3');
          return JSON.parse(responseText);
        },
      ];
    }
    //post请求
    if (config.method === 'post') {
    //请求参数是formmDta类型(例如文件上传),需要模板form表单,避免post请求参数丢失
      if (config.data instanceof FormData) {
        const data = Vue.prototype.baseRequestData(config);
        for (let key in data) {
          config.data.append(key, data[key]);
        }
      } else {
      //普通post请求
        requestData = Vue.prototype.$deleteKey(Object.assign({}, Vue.prototype.baseRequestData(config), config.data));
        token = Vue.prototype.$setToken(requestData);
        config.data = qs.stringify(Object.assign({}, requestData, { X_Public_Token: token }));
      }
    } else if (config.method === 'get') {
    //get请求
      requestData = Vue.prototype.$deleteKey(Object.assign({}, Vue.prototype.baseRequestData(config), config.params));
      token = Vue.prototype.$setToken(requestData);
      config.params = Object.assign({}, requestData, { X_Public_Token: token });
    }
    return config;
  },
  err => {
    return Promise.reject(err);
  },
);

// http 相应拦截器
/**
 * 拦截器也可以判定返回的response成功时的状态码进行拦截
 */
axios.interceptors.response.use(
  async res => {
  //我的接口返回的字段我可以根据这个标识来判断请求成功或者是吧,然后做些全局提示等等
    if (!res.data.Success) {
      switch (parseInt(res.data.Code)) {
        case 34:
        //状态码34(我这代表未登录,返回首页,自己根据接口来判断)
          await Vue.prototype.$logoutSystem();
          break;
      }
      //请求失败全局提示
      Vue.prototype.$Message.error(res.data.Description);
    }
    return res;
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 500:
        //状态码500的时候,服务端错误
          Vue.prototype.$Message.error('服务端错误');
      }
    }
  },
);
export default axios;