UNPKG

instruct-request-axios

Version:
505 lines (415 loc) 17.4 kB
import {AxiosError, AxiosInstance, default as axios} from 'axios'; import { RequestConfigInstruction, ResponseData, RequestPlugin, InstructionPostOption, ResponseSuccess, InstructionOption, ExitTriggers, InstructionExit, ResponseTypeStatus, RequestResponse, RequestPluginExtends, RequestMessageOption, RequestAgentFunction, ReuqestAgentTypeName, DefaultRequestConfigInstruction, ResponseExtendChain } from './type.d'; import Instructions, { InstructionType, InstructionConfigObject, InstructionConfig, InstructionTriggerType } from '../instructions/index'; import SparkMD5 from "spark-md5"; import PromiseExtend from "../extend/ProsmiseExtend"; let signObject = {}; ['url','data','headers','method','responseCode','codeKey','rest','params','responseType','xsrfCookieName','xsrfHeaderName','maxContentLength','maxBodyLength','maxRedirects','socketPath','httpAgent','httpsAgent','cancelToken','baseURL','auth','timeoutErrorMessage'].map((item)=>{ signObject[item] = 1; }); export default class Request<warpT=RequestResponse,warpD=AxiosError<DefaultRequestConfigInstruction>,warpE extends DefaultRequestConfigInstruction=DefaultRequestConfigInstruction> extends Instructions{ protected defaultConfig:RequestConfigInstruction<warpT,warpD,warpE>= { responseCode:[200], codeKey:'code', rest:true } public message(key:RequestMessageOption,requestConfig:InstructionPostOption,option:string | {content:string,duration?:number,onClose?:Function}){ let config = this.getConfig('message',requestConfig); let triggerFunction = config && config[key] || this.config.message && this.config.message[key]; // 如果存在触发函数 if(triggerFunction) { if(typeof option === 'string') option = {content:option}; return triggerFunction(option.content,option.duration,option.onClose); } } // @ts-ignore public push(instruction:InstructionConfig<InstructionPostOption>,name:string='default',triggerType?:InstructionTriggerType,zIndex:number =0):InstructionConfigObject<InstructionPostOption>{ return super.push<InstructionPostOption>(instruction, name, triggerType, zIndex); } // 默认的配置器 protected config:RequestConfigInstruction<warpT,warpE,warpD> // 接口请求器 public $request:AxiosInstance; // 创建配置文件 constructor(config:RequestConfigInstruction<warpT,warpE,warpD>) { super(); // 创建配置文件 if (config) { // 创建配置文件 config = Object.assign({},this.defaultConfig,config); } else { // @ts-ignore config = Object.assign({},this.defaultConfig); } // 创建请求对象 this.$request = axios.create(config); // 存储配置文件 this.config = config; } // 签名列表 protected signObject:Record<string, number> = signObject; // 创建签名 protected sign(requestConfig:DefaultRequestConfigInstruction):string{ let keys = Object.keys(requestConfig); let sign = ''; for (let i=0,count=keys.length;i<count;i++) { if (this.signObject[keys[i]] && requestConfig[keys[i]] !== undefined) { let type = typeof requestConfig[keys[i]]; if (type === 'object') { try { sign += JSON.stringify(requestConfig[keys[i]]); } catch (e) { sign += requestConfig[keys[i]]; } } else if (type === 'string') { sign += type; } else { sign += requestConfig[keys[i]] } } } return SparkMD5.hash(sign); } // 执行指令 public createFront(requestConfig:DefaultRequestConfigInstruction,triggers:ExitTriggers,callback?:Function):InstructionOption | void{ // 创建退出函数 const exit: InstructionExit = <InstructionExit<ResponseData>>function (value, status = "none", end: boolean = true) { if (!exit.next) return; if (status === "none") { value && console.info('request exit:', value); end = true; } let trigger = exit.triggers[status]; if (end) { exit.triggers = null; exit.next = false; } return trigger && trigger(value); }; exit.triggers = triggers; exit.next = true; // 创建配置指令 let config:InstructionOption = { exit: exit, // @ts-ignore requestData: requestConfig, sign: "", status: "loading", // @ts-ignore introduces: requestConfig } // 执行入口设置 if (this.triggerInstruction<InstructionOption>(this.agentSearch(config,"entry"),config)) { callback && callback(); config = Object.assign(config,{ introduces:Object.assign({},config.introduces), sign:this.sign(config.requestData) }); // 返回执行 if (this.triggerInstruction<InstructionOption>(this.agentSearch(config,"front"),config)) { return config; } } } // 执行搜索代理 protected agentSearch<T extends InstructionOption>(config:T,type:InstructionType = "front"):Array<InstructionConfigObject>{ config.type = type; return this.search(config.introduces,config,type); } // 执行 protected triggerInstruction<T extends InstructionOption>(data: Array<InstructionConfigObject>, option: T): boolean { let resultOption = option; option = Object.assign({},option); for (let i=0,count=data.length;i<count;i++) { data[i].trigger(option); if (!option.exit.next) { return false; } } resultOption.extend = option.extend; return true; } // 执行后续 public triggerPost(config:InstructionPostOption,callback?:Function,end:boolean=true,restAll:boolean = false){ // 执行后置处理 if (this.triggerInstruction<InstructionPostOption>(this.agentSearch( config, "post" ),config)) { let status:ResponseTypeStatus = config.status === "success" ? "success" : "fail" if(status === 'fail' && config.responseData.constructor && config.responseData.constructor.name === 'Cancel') { config.responseData = { data:null, status: 500, statusText: (config.responseData as any).message, config:undefined, headers:undefined, custom:true, cancel:true }; } // 执行相应的处理 if (this.triggerInstruction<InstructionPostOption>(this.agentSearch( config, status ),config)) { let exit = config.exit; let responseData = config.responseData; if(!restAll) { responseData = this.getSuccessDataMode(config) } delete config.extend; config = null; return exit(responseData,status,end); } } return callback && callback(); } // 如果为成功执行设置数据 getSuccessDataMode(config:InstructionPostOption){ if (config.status !== 'success') return config.responseResultData || config.responseData; let responseData = config.responseResultData; let ResponseData = function (obj:any,isObject:boolean) { if (isObject) { for (let key in obj) { if (obj.hasOwnProperty(key)) { this[key] = obj[key]; } } } else { this.data = obj; } }; let isObject = responseData && typeof responseData === 'object' && !(responseData instanceof Array); if (isObject) config.responseExtendChain.__isObject = isObject; ResponseData.prototype = config.responseExtendChain; responseData = new ResponseData(responseData,isObject); return responseData; } // 请求合并 all<T=warpT,T1=warpT,T2=warpT,T3=warpT,T4=warpT,T5=warpT,T6=warpT,T7=warpT>(data:Array<PromiseExtend<T | T1 | T2 | T3 | T4 | T5 | T6 | T7>> | ((config:DefaultRequestConfigInstruction)=> Array<PromiseExtend<T | T1 | T2 | T3 | T4 | T5 | T6 | T7>>),requestConfig?:DefaultRequestConfigInstruction):PromiseExtend<Array<(T | T1 | T2 | T3 | T4 | T5 | T6 | T7) & ResponseExtendChain>,warpD> { let promiseExtend = new PromiseExtend<Array<(T | T1 | T2 | T3 | T4 | T5 | T6 | T7) & ResponseExtendChain>,warpD>((resolve,reject)=>{ // 创建配置文件 let config = this.createFront(requestConfig || {},{ "success":resolve, "fail":reject }) as InstructionPostOption; if(config) { if(typeof data === 'function') { data = data(config.requestData); } PromiseExtend.all(data).then((response)=>{ return this.setSuccessResponseData(response,config,true); }).catch((response)=>{ // @ts-ignore config.responseData = response; config.status = "fail"; }).finally(()=>{ return this.triggerPost(config,function (){ promiseExtend = null; config = null; },true,true); }); } else { promiseExtend = null; config = null; } }) return promiseExtend; } // 请求 request<T=warpT,D=warpD>(requestConfig:DefaultRequestConfigInstruction):PromiseExtend<T,D>{ let promiseExtend = new PromiseExtend<T,D>( (resolve, reject)=> { // 创建配置文件 let config = this.createFront(requestConfig,{ "success":resolve, "fail":reject }) as InstructionPostOption; if (config) { return this.$request(config.requestData).then((response)=>{ return this.setSuccessResponseData(response,config); }).catch((response)=>{ config.responseData = response; config.status = "fail"; }).finally(()=>{ return this.triggerPost(config,function (){ promiseExtend = null; config = null; }); }); } else { promiseExtend = null; config = null; } }); return promiseExtend; } // 上传文件 upload<T=warpT,D=warpD>(requestConfig:DefaultRequestConfigInstruction):PromiseExtend<T,D>{ let promiseExtend = new PromiseExtend<T,D>( (resolve, reject)=> { // 创建配置文件 let config = this.createFront(requestConfig,{ "success":resolve, "fail":reject }) as InstructionPostOption; if (config) { return this.$request({ ...requestConfig, data:function() { if(requestConfig.data) { let formData = new FormData(); for(let key in requestConfig.data) { if(requestConfig.data.hasOwnProperty(key)) { formData.append(key,requestConfig.data[key]); } } return formData; } else { return undefined; } }(), headers:{ 'content-type':'multiple/form-data', ...(requestConfig.headers || {}) } }).then((response)=>{ this.setSuccessResponseData(response,config); }).catch((response)=>{ config.responseData = response; config.status = "fail"; }).finally(()=>{ return this.triggerPost(config,function (){ promiseExtend = null; config = null; }); }); } else { promiseExtend = null; config = null; } }); return promiseExtend; } // 代理表 agentData:{[key in ReuqestAgentTypeName]?:RequestAgentFunction<any,any,any>}; // 获取代表 getAgentTarget<T,I,D>(name:ReuqestAgentTypeName):RequestAgentFunction<T,I,D>{ if(!this.agentData) return; return this.agentData[name]; } // 代理 agent<T extends warpT=warpT,D extends warpD = warpD>(name:ReuqestAgentTypeName,target:RequestAgentFunction<T,any,D>){ if(this.agentData === undefined) this.agentData={}; this.agentData[name] = target; } // 安装插件 use<T>(plugin:RequestPlugin,option?:T){ plugin.install(this as any,option); plugin.extendName && plugin.extend && this.insertExtend(plugin); return this; } // 插入 insertExtend(plugin:RequestPlugin){ if (plugin.extendName && plugin.extend) { if (!this.extendValues) this.extendValues = {}; this.extendValues[plugin.extendName] = { trigger:plugin.extend, option:plugin.extendOption }; } } // 扩展开放属性 extendValues:Record<string, RequestPluginExtends>; // 获取配置 getConfig<T extends keyof warpE>(key:T,config?:InstructionPostOption,option?:{[key in T]?:warpE[T]}):warpE[T] | void{ if(option && option[key]){ return option[key] } if (config && config.introduces.hasOwnProperty(key)) return config.introduces[key as keyof DefaultRequestConfigInstruction]; if (this.config.hasOwnProperty(key)) { return this.config[key as keyof DefaultRequestConfigInstruction]; } else { return; } } // 注册扩展模块 registerExtend<T=any,D=any>(that:RequestPlugin,config:InstructionPostOption,option?:T,resultOption?:D){ return that.registerExtend && that.registerExtend(config.responseExtendChain,option,resultOption,config); } // 获取扩展配置 getExtend<T>(that:RequestPlugin,config:InstructionPostOption):T | undefined { if (config.extend) { return config.extend[that.extendName]; } return undefined; } // 设置扩展配置 setExtend<T>(that:RequestPlugin,value:T,config:InstructionPostOption){ if (!config.extend) config.extend = {}; config.extend[that.extendName] = value; } // 开放函数 校验是否为 成功 verificationSuccessful(response:ResponseData,option:ResponseSuccess,config:InstructionPostOption):boolean{ // 获取校验函数 let customCheck = option.customCheck || this.getConfig('customCheck',config); if (customCheck) { return customCheck(response,option); } else { if (!response.data) return false; // 获取成功状态码 let responseCode = option.hasOwnProperty('responseCode') ? option.responseCode : this.getConfig('responseCode',config); // 获取 codeKey let codeKey = option.codeKey || this.getConfig('codeKey',config); if(codeKey) { // 返回执行结果 if (!responseCode || (responseCode as Array<any>).length <= 0) return true; try { return (responseCode as Array<any>).includes(response.data[codeKey]); } catch (e) { return false; } } else { return false; } } } // 设置成功的数据 setSuccessResponseData(response:ResponseData | any,config:InstructionPostOption,setAll:boolean=false){ config.status = 'success'; config.responseData = response; if(!setAll) { config.responseRestData = response.data; config.responseExtendChain = { __sign:config.sign, isSuccess: this.verificationSuccessful(response, Object.assign({},this.config,config.requestData),config) }; // 是否展开 let rest = this.getConfig('rest',config); if (rest) { config.responseResultData = response.data; } else { config.responseResultData = response; } } } }