import axios from 'axios' import { default as defaultConfig } from './config' import { default as defaultInterceptors } from './interceptors' import promiseCacheRequest from './promiseCacheRequest' export default class Service { // 拦截器类型列表 static INTERCEPTOR_TYPE_LIST = ['request', 'response'] static INTERCEPTOR_ENFORCE_WEIGHT_MAP = { pre: -1, normal: 0, post: 1 } // 拦截器enforce属性权重,值越小执行顺序越靠前 // 通过use注册的拦截器 static registeredInterceptors = [] constructor({ config = {}, interceptors = [] } = {}) { this.config = this.getConfig(config) this.interceptors = this.getInterceptors(interceptors) this.axiosInstance = this.init() this.applyAllInterceptors() this.overrideMethods() } /** * 重写request方法 * @param {Object} config 请求配置对象 * @returns * @memberof Service */ overrideRequest(config) { return promiseCacheRequest(config, this.axiosInstance.request) } /** * 复写axiosInstance请求方法 * @memberof Service */ overrideMethods() { const methodList = [ 'request', 'get', 'delete', 'head', 'options', 'post', 'put', 'patch', 'getUri', ] methodList.forEach(method => { this[method] = (...params) => { let url, data, config switch (method) { case 'get': case 'delete': case 'head': case 'options': ;[url, config] = params || [] break case 'post': case 'put': case 'patch': ;[url, data, config] = params || [] break case 'request': case 'getUri': default: ;[config] = params break } return this.overrideRequest({ method, url, data, ...config, }) } }) } // 初始化axios实例 init() { const axiosInstance = axios.create(this.config) return axiosInstance } /** * 获取配置对象 * @param {Object} config 传入配置对象 * @returns {Object} 最终配置对象 * @memberof Service */ getConfig(config = {}) { return Object.assign({}, defaultConfig, config) } /** * 获取拦截器 * @param {Array} interceptors 拦截器列表 * @returns {Array} 最终拦截器列表 * @memberof Service */ getInterceptors(interceptors = []) { const allInterceptors = [ ...defaultInterceptors, ...Service.registeredInterceptors, ...interceptors, ] const filterInterceptors = this.filterInterceptors(allInterceptors) const sortInterceptors = this.sortInterceptors(filterInterceptors) return sortInterceptors } /** * 对拦截器根据enforce属性排序 * @param {Array} interceptors * @memberof Service */ sortInterceptors(interceptors) { if (!(interceptors && interceptors.length)) { return [] } return interceptors.sort((a, b) => { const { enforce: aEnforce = 'normal' } = a const { enforce: bEnforce = 'normal' } = b const normalWeight = Service.INTERCEPTOR_ENFORCE_WEIGHT_MAP['normal'] const aEnforceWeight = Service.INTERCEPTOR_ENFORCE_WEIGHT_MAP[aEnforce] || normalWeight const bEnforceWeight = Service.INTERCEPTOR_ENFORCE_WEIGHT_MAP[bEnforce] || normalWeight return aEnforceWeight - bEnforceWeight }) } /** * 应用拦截器 * @param {Object} interceptor 拦截器 * @param {boolean} isTail 拦截器是否处于尾部 * @memberof Service */ applyInterceptor(interceptor, isTail) { const { type, onFulfilled, onRejected } = interceptor if (this.validateInterceptorType(type)) { this.axiosInstance.interceptors[type].use( val => onFulfilled(val, isTail), error => onRejected(error, isTail) ) } } /** * 注册拦截器 * @param {Object} interceptor * @param {string} interceptor.type 拦截器类型 ['request'|'response'] * @param {string} interceptor.enforce 拦截器enforce顺序 ['pre'|'normal'|'post'],默认normal * @param {Function} interceptor.onFulfilled 拦截器成功回调 * @param {Function} interceptor.onRejected 拦截器失败回调 * @memberof Service */ use(interceptor, config = { pre: false }) { if (config.pre) { Service.defaultInterceptors.unshift(interceptor) } else { Service.defaultInterceptors.push(interceptor) } } /** * 取消拦截器 * @param {string} type 拦截器类型 * @param {number} id 拦截器id * @memberof Service */ ejectInterceptor(type, id) { if (this.validateInterceptorType(type)) { this.axiosInstance.interceptors.request.eject(id) } } /** * 验证拦截器类型 * @param {string} type 拦截器类型 * @returns {boolean} 是否是合法的拦截器 * @memberof Service */ validateInterceptorType(type) { if (!Service.INTERCEPTOR_TYPE_LIST.includes(type)) { throw new Error('未知拦截器类型') } return true } // 应用所有拦截器 applyAllInterceptors() { try { if (!(this.interceptors && this.interceptors.length)) { return } this.interceptors.map((interceptor, index) => { const isTail = index === this.interceptors.length - 1 this.applyInterceptor(interceptor, isTail) }) } catch (error) { console.log(error) } } /** * 对拦截器处理,同名同类型进行覆盖 * @param {Array} allInterceptors 拦截器列表 * @returns {Array} 最终拦截器列表 * @memberof Service */ filterInterceptors(allInterceptors = []) { if (!allInterceptors.length) { return [] } let map = new Map() let arr = [] for (let index = allInterceptors.length - 1; index > 0; index--) { const ele = allInterceptors[index] let key = ele.name + '-' + ele.type if (!map.has(key)) { map.set(key, ele) } } for (let value of map.values()) { arr.unshift(value) } return arr } }