From c91ebc3eb36dfd246ca30800afd5bb5bc3569464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E4=BA=9A=E6=98=95?= <1549469775@qq.com> Date: Thu, 5 Dec 2024 17:25:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20http=E6=8F=92=E4=BB=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/http/base.ts | 66 +++++++++++++++++++++++++++------ src/plugins/http/index.ts | 43 ++++++++++++++++++--- src/plugins/http/plugins/Loading.ts | 74 +++++++++++++++++++++++++++---------- 3 files changed, 146 insertions(+), 37 deletions(-) diff --git a/src/plugins/http/base.ts b/src/plugins/http/base.ts index 2ed8679..f4fd915 100644 --- a/src/plugins/http/base.ts +++ b/src/plugins/http/base.ts @@ -25,6 +25,11 @@ export class Plugin implements IPlugin { destory() { } } +export const enum EFor { + Continue, + Break, +} + export abstract class PluginsManager { static plugins: IPlugin[] = [] static use(plugin: IPlugin | IPlugin[]) { @@ -34,28 +39,44 @@ export abstract class PluginsManager { } plugins: IPlugin[] = [] + exculdPlugins: string[] = [] + use(plugin: IPlugin) { if (Array.isArray(plugin)) { this.plugins = this.plugins.concat(plugin) } else this.plugins.push(plugin) } - callPluginByName(name: string, key: keyof T, ...argus: any[]) { + async runPlugins(cb: (p: IPlugin) => Promise) { + const array = [...PluginsManager.plugins, ...this.plugins] + for (let i = 0; i < array.length; i++) { + let p = array[i] + let result = await cb(p) + if (result === EFor.Continue) { + continue + } else if (result === EFor.Break) { + break + } + } + } + async _callPluginByName(name: string, key: keyof T, ...argus: any[]) { const array = [...PluginsManager.plugins, ...this.plugins] for (let i = 0; i < array.length; i++) { let p = array[i] + if (this.exculdPlugins.includes(p.name)) continue if (!p.name) continue if (name === p.name) { const fn = (p as T)[key] - typeof fn === "function" && fn.apply(p, argus) + typeof fn === "function" && await fn.apply(p, argus) } } } - callPlugin(key: keyof IPlugin, ...argus: any[]) { + async _callPlugin(key: keyof IPlugin, ...argus: any[]) { const array = [...PluginsManager.plugins, ...this.plugins] for (let i = 0; i < array.length; i++) { let p = array[i] + if (this.exculdPlugins.includes(p.name)) continue const fn = p[key] - typeof fn === "function" && fn.apply(p, argus) + typeof fn === "function" && await fn.apply(p, argus) } } } @@ -66,24 +87,45 @@ export abstract class httpBase extends PluginsManager { requestInterceptorId: null | number = null responseInterceptorId: null | number = null + async callPluginByName(name: string, key: keyof T, ...argus: any[]) { + await this.runPlugins(async (p) => { + if (this.exculdPlugins.includes(p.name)) return EFor.Continue + if (!p.name) return EFor.Continue + if (name === p.name) { + const fn = (p as T)[key] + typeof fn === "function" && await fn.apply(p, argus) + } + }) + // await this._callPluginByName(name, key, ...argus) + } + + async callPlugin(key: keyof IPlugin, ...argus: any[]) { + await this.runPlugins(async (p) => { + if (this.exculdPlugins.includes(p.name)) return EFor.Continue + const fn = p[key] + typeof fn === "function" && await fn.apply(p, argus) + }) + // await this._callPlugin(key, ...argus) + } + create(config?: CreateAxiosDefaults) { this.instance = axios.create(deepAssign>(axios.defaults, config ?? {})) - this.requestInterceptorId = this.instance.interceptors.request.use(config => { + this.requestInterceptorId = this.instance.interceptors.request.use(async config => { const argu = { config } - this.callPlugin("beforeRequestConfig", argu) + await this.callPlugin("beforeRequestConfig", argu) return argu.config - }, error => { + }, async error => { const argu = { error } - this.callPlugin("beforeRequestError", argu) + await this.callPlugin("beforeRequestError", argu) return Promise.reject(argu.error) }) - this.responseInterceptorId = this.instance.interceptors.response.use(response => { + this.responseInterceptorId = this.instance.interceptors.response.use(async response => { const argu = { response } - this.callPlugin("beforeResponse", argu) + await this.callPlugin("beforeResponse", argu) return Promise.resolve(argu.response) - }, (error) => { + }, async (error) => { const argu = { error } - this.callPlugin("beforeResponseError", argu) + await this.callPlugin("beforeResponseError", argu) return Promise.reject(argu.error) }) return this.instance diff --git a/src/plugins/http/index.ts b/src/plugins/http/index.ts index a8248f8..057e64c 100644 --- a/src/plugins/http/index.ts +++ b/src/plugins/http/index.ts @@ -3,6 +3,15 @@ import { CreateAxiosDefaults, AxiosRequestConfig, AxiosResponse } from "axios" const FlyPoll: Map = new Map() +interface ICallFly { + pass: (argus: { exculdPlugins?: string[] }) => Fly + get: (...argus: [url: string, config?: AxiosRequestConfig | undefined]) => () => Promise> + post: (...argus: [url: string, config?: AxiosRequestConfig | undefined]) => () => Promise> + put: (...argus: [url: string, config?: AxiosRequestConfig | undefined]) => () => Promise> + delete: (...argus: [url: string, config?: AxiosRequestConfig | undefined]) => () => Promise> + request: (...argus: [config: AxiosRequestConfig]) => () => Promise> +} + class Fly extends httpBase { static disposeAll() { if (FlyPoll.size) { @@ -32,8 +41,25 @@ class Fly extends httpBase { if (!instance) { throw new Error("未初始化此实例") } + instance.exculdPlugins = [] return instance } + static callFn(name?: string): ICallFly { + if (!name) name = "$defalut" + const instance = FlyPoll.get(name) + if (!instance) { + throw new Error("未初始化此实例") + } + instance.exculdPlugins = [] + return new Proxy(instance, { + get(target, p: string) { + if (["get", "post", "put", "delete", "request"].includes(p.toLowerCase())) { + return (...argus: any[]) => () => target[p](...argus) + } + return target[p] + }, + }) + } static get method() { return { @@ -59,6 +85,11 @@ class Fly extends httpBase { } } + pass({ exculdPlugins }: { exculdPlugins?: string[] }) { + this.exculdPlugins = exculdPlugins ?? [] + return this + } + name: string constructor(name: string) { @@ -80,15 +111,15 @@ class Fly extends httpBase { request(...argus: [config: AxiosRequestConfig]) { return this.instance!.request.apply(this.instance, argus) as Promise> } - #init(config: AxiosRequestConfig) { - this.callPlugin("beforeCreate") + async #init(config: AxiosRequestConfig) { + await this.callPlugin("beforeCreate") this.create(config) - this.callPlugin("created") + await this.callPlugin("created") } - #destory() { - this.callPlugin("beforeDestory") + async #destory() { + await this.callPlugin("beforeDestory") this.destory() - this.callPlugin("destory") + await this.callPlugin("destory") } } diff --git a/src/plugins/http/plugins/Loading.ts b/src/plugins/http/plugins/Loading.ts index f6379cc..2e92507 100644 --- a/src/plugins/http/plugins/Loading.ts +++ b/src/plugins/http/plugins/Loading.ts @@ -12,13 +12,15 @@ type AxiosRequestConfigPlus = AxiosRequestConfig & { $loading_ToastID?: Id $loading_CreateTimeStamp?: number $loading_ToastShowFn?: () => void - $loading_ToastHideFn?: () => void + $loading_ShowTimerId?: NodeJS.Timeout } interface IConfig { text: string min: number minShow: boolean + minSync: boolean + minShowLong: number } // 取消重复请求 @@ -30,6 +32,8 @@ export class LoadingPlugin implements IPlugin { text: "加载中", min: 1000, minShow: false, + minSync: true, + minShowLong: 1000, } config: IConfig = JSON.parse(JSON.stringify(this.defaultConfig)) @@ -62,36 +66,68 @@ export class LoadingPlugin implements IPlugin { if (!this.getConfig("minShow", config.loadingAttrs)) { config.$loading_ToastShowFn() delete config.$loading_ToastShowFn + } else { + config.$loading_ShowTimerId = setTimeout(() => { + config.$loading_ToastShowFn!() + delete config.$loading_ToastShowFn + }, this.getConfig("min", config.loadingAttrs)); } } beforeResponse({ response }: { response: AxiosResponse }) { - const { config } = response as { config: AxiosRequestConfigPlus } - if (!this.getConfig("minShow", config.loadingAttrs)) { - const min = this.getConfig("min", config.loadingAttrs) - if (config.$loading_ToastID) { - const [ToastID, showTimeStamp] = [config.$loading_ToastID, config.$loading_CreateTimeStamp] - const oft = new Date().getTime() - showTimeStamp! - if (oft < min) { - setTimeout(() => { + return new Promise((resolve) => { + const over = (isOver: boolean) => { + if (isOver) { + resolve(void 0) + } + } + const { config } = response as { config: AxiosRequestConfigPlus } + clearTimeout(config.$loading_ShowTimerId) + if (!this.getConfig("minShow", config.loadingAttrs)) { + const min = this.getConfig("min", config.loadingAttrs) + if (config.$loading_ToastID) { + const [ToastID, showTimeStamp] = [config.$loading_ToastID, config.$loading_CreateTimeStamp] + const oft = new Date().getTime() - showTimeStamp! + if (oft < min) { + setTimeout(() => { + toast.dismiss(ToastID) + over(this.getConfig("minSync", config.loadingAttrs)) + }, min - oft); + } else { + over(this.getConfig("minSync", config.loadingAttrs)) + toast.dismiss(ToastID) + } + delete config.$loading_ToastID + delete config.$loading_CreateTimeStamp + } + } else { + if (config.$loading_ToastID) { + const min = this.getConfig("minShowLong", config.loadingAttrs) + const [ToastID, showTimeStamp] = [config.$loading_ToastID, config.$loading_CreateTimeStamp] + const oft = new Date().getTime() - showTimeStamp! + if (oft < min) { + setTimeout(() => { + toast.dismiss(ToastID) + over(this.getConfig("minSync", config.loadingAttrs)) + }, min - oft); + } else { + over(this.getConfig("minSync", config.loadingAttrs)) toast.dismiss(ToastID) - }, min - oft); - } else { - toast.dismiss(ToastID) + } + delete config.$loading_ToastID + delete config.$loading_CreateTimeStamp } - delete config.$loading_ToastID - delete config.$loading_CreateTimeStamp } - } else { - - } - + over(!this.getConfig("minSync", config.loadingAttrs)) + }) } beforeResponseError(argu: { error: AxiosError }) { const requestConfig = argu.error.config! as AxiosRequestConfigPlus + clearTimeout(requestConfig.$loading_ShowTimerId) if (requestConfig.$loading_ToastID) { - const [ToastID] = requestConfig.$loading_ToastID.split("$") + const [ToastID] = [requestConfig.$loading_ToastID, requestConfig.$loading_CreateTimeStamp] toast.dismiss(ToastID) delete requestConfig.$loading_ToastID + delete requestConfig.$loading_CreateTimeStamp } } }