/** axios封装 * 请求拦截、相应拦截、错误统一处理 */ import axios from 'axios' // const http = axios.create() export default class BaseAxios { /** * constructor 构造函数 * @param {Object} conf 实例全局配置,配置项基本同 defaultConf */ constructor(conf = {}) { this.defaultConf = { // baseURL: process.env.VUE_APP_API_HOST, timeout: 30000, method: 'post', headers: { 'Content-Type': 'application/json;charset=UTF-8' }, withCredentials: true, responseType: 'json' } this.specialParamsKeys = [ 'data', 'method', 'headers', 'withCredentials', 'responseType' ] this.init(conf) } /** * 初始化,合并配置 * @param {Object} conf 全局配置 */ init(conf) { const { defaultConf } = this this.conf = Object.assign({}, { ...defaultConf }, { ...conf }) } /** * post 请求处理 * @param {String} api 接口地址 * @param {Object|String} params 请求参数 */ post(api, params = {}, conf = {}) { return this.request(api, params, { method: 'post', ...conf }) } /** * get 请求处理 * @param {String} api 接口地址 * @param {Object|String} params 请求参数 */ get(api, params = {}, conf = {}) { return this.request(api, params, { method: 'get', ...conf }) } /** * mixParams 参数混入处理,可供实例后续扩展 * @param {Object|String} params 请求参数 */ mixParams(params) { const { specialParamsKeys } = this if (typeof params === 'string') { params = { data: params } } if (typeof params === 'object') { // 若参数中包含配置信息,则不需要特殊处理(此时的实际参数为params的data字段) if (!Object.keys(params).some(key => specialParamsKeys.includes(key))) { params = { data: params } } } return params } /** * mixConf 合并配置项 * @param {Object} conf 请求配置项 * @param {Object} params 参数或包含参数的配置项 @example {data: {name: 'someone'}} */ mixConf(conf = {}, params = {}) { return Object.assign( {}, { ...this.conf }, { ...conf }, { ...this.mixParams(params) } ) } /** * getUrl 获取请求url完整地址 * @param {String} api请求地址 * @param {Object} mixConf 混入后的请求配置 */ getUrl(api, mixConf) { const { method = 'post', baseURL = '', data = {} } = mixConf // 避免/符号重复 let url = baseURL === '' ? baseURL : `${baseURL.replace(/\/+$/, '')}/` // 如果是完整http路径,则不用拼接baseURL前缀 if (api.search(/^https?:\/\//) !== 0) { api = `${url}${api.replace(/^\/+/, '')}` } if (method.toLocaleLowerCase() === 'get') { const str = this.getUrlParams(data) api = api.includes('?') ? `${api}&${str}` : `${api}?${str}` } return api } /** * getUrlParams 拼接url字符串 * @param {String} api 接口地址 * @param {Object|String} params 请求参数 */ getUrlParams(params) { if (typeof params === 'object') { params = Object.keys(params).reduce((pre, curr) => { const val = typeof params[curr] === 'object' ? JSON.stringify(params[curr]) : params[curr] pre = pre === '' ? pre : `${pre}&` pre = `${pre}${curr}=${val}` return pre }, '') } return params } /** * getParams 根据headers信息, * @param {Object} mixConf 请求配置项 */ getParams(mixConf) { let { data = {}, headers = {} } = mixConf Object.keys(headers).forEach(key => { if (key.toLocaleLowerCase() === 'content-type') { // json string if ( headers[key].includes('application/json') && typeof data !== 'string' ) { data = JSON.stringify(data) } // params if (headers[key].includes('application/x-www-form-urlencoded')) { data = this.getUrlParams(data) } // file if ( headers[key].includes('multipart/form-data') && !(data instanceof FormData) ) { const formData = new FormData() Object.keys(data).forEach(key => { formData.append(key, data[key]) }) data = formData } } }) return data } /** * 请求统一入口 * @param {String} api 接口地址 * @param {Object|String} params 请求参数 * @param {Object} conf 请求配置信息 */ request(api, params = {}, conf = {}) { const mixConf = this.mixConf(conf, params) const url = this.getUrl(api, mixConf) const data = this.getParams(mixConf) return this.axios({ ...mixConf, url, data }) } /** * 原始axios请求方法 * @param {Object} conf 请求配置 */ axios(conf = {}) { return axios.create()(conf) } }