基于axios.js的二次封装

基于axios.js的二次封装

通常情况下, 直接的去使用axios库并不是那么优雅, 使得代码可读性下降, 不易于维护, 所以有了如下对axios的二次封装

// 配置环境变量
process.env.BASE_API = 'your api url';
process.env.REQUEST_TIMEOUT = 30 * 1000;
// utils.js
// 深冻结
export function deepFreeze (o) {
  Object.freeze(o);

  Object.getOwnPropertyNames(o).forEach(function (prop) {
    if (o.hasOwnProperty(prop) &&
      o[prop] !== null &&
      (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
      !Object.isFrozen(o[prop])) {
      deepFreeze(o[prop]);
    }
  });

  return o;
}
// http.js
import axios from 'axios';
import pickBy from 'lodash/pickBy';
import { deepFreeze } from '@/utils';
import { Message } from 'element-ui';

const TOKEN_KEY = 'X-ACCESS-TOKEN';

/**
 * 过滤 null, undefined, NaN
 */
function identity (o) {
  return !(o === null || o === undefined || (typeof o === 'number' && o != +o));
}

// 全局配置
axios.defaults.baseURL = process.env.BASE_API;
// axios.defaults.baseURL = 'http://127.0.0.1/inx';
axios.defaults.headers = {
  // 'X-ACCESS-TOKEN': AUTHENTICATION_KEY
};
// axios.defaults.withCredentials = true;
// axios.defaults.timeout = process.env.REQUEST_TIMEOUT;

// Add a request interceptor
axios.interceptors.request.use(function (config) {
  // Do something before request is sent
  if (store.getters.token) {
    // 让每个请求携带自定义token 请根据实际情况自行修改
    config.headers[TOKEN_KEY] = getToken();
  }

  return config;
}, function (error) {
  // for debug
  // Do something with request error
  return Promise.reject(error);
});

// Add a response interceptor
axios.interceptors.response.use(function (response) {
  const res = response.data;

  // if the custom code is not 0, it is judged as an error.
  if (res.errno !== 0) {
    Message.closeAll();
    Message({
      message: res.msg || 'Error',
      type: 'error',
      duration: 5 * 1000
    });

    // 101: Token expired;
    if (res.errno === 101) {
      // to re-login
      // location.reload();
    }

    return Promise.reject(new Error(res.msg || 'Error'));
  } else {
    return deepFreeze(res.data);
  }
}, function (error) {
  // for debug
  console.log('err: ' + error);
  Message.closeAll();
  // Do something with response error
  if (error.response) {
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    });
    return Promise.reject(error.response.data || error);
  } else {
    Message({
      message: 'Network error',
      type: 'error',
      duration: 5 * 1000
    });
    return Promise.reject(new Error('Network error'));
  }
});

// axios
export const http = {
  get (url = '', params = {}) {
    const cb = arguments[arguments.length - 1];
    if (arguments.length > 2 && typeof cb === 'function') {
      return axios({
        method: 'get',
        url,
        params: pickBy(params, identity)
      }).then(function (result) {
        cb(null, result);
      }).catch(function (err) {
        cb(err, null);
      });
    } else {
      return axios({
        method: 'get',
        url,
        params: pickBy(params, identity)
      });
    }
  },

  post (url = '', data = {}) {
    const cb = arguments[arguments.length - 1];
    if (arguments.length > 2 && typeof cb === 'function') {
      return axios({
        method: 'post',
        url,
        data: pickBy(data, identity)
      }).then(function (result) {
        cb(null, result);
      }).catch(function (err) {
        cb(err, null);
      });
    } else {
      return axios({
        method: 'post',
        url,
        data: pickBy(data, identity)
      });
    }
  },

  all (arr) {
    return axios.all(arr).then(axios.spread((...args) => args));
  },

  /**
   * Syntactic sugar for invoking a function and expanding an array for arguments.
   *
   * Common use case would be to use `Function.prototype.apply`.
   *
   *  ```js
   *  function f(x, y, z) {}
   *  var args = [1, 2, 3];
   *  f.apply(null, args);
   *  ```
   *
   * With `spread` this example can be re-written.
   *
   *  ```js
   *  spread(function(x, y, z) {})([1, 2, 3]);
   *  ```
   *
   * @param {Function} callback
   * @returns {Function}
   */
  spread (callback) {
    return function wrap (arr) {
      return callback.apply(null, arr);
    };
  }
};

export const headers = function () {
  return {
    [TOKEN_KEY]: getToken()
  };
};

export const request = axios;

export default { http, headers, request };

// Use http.js
import { http } from 'http.js;

http.get('/api/user', [params]).then().catch();
http.post('/api/user', [data]).then().catch();