diff --git a/miniprogram/app.ts b/miniprogram/app.ts index 004bd19..ba8fa89 100644 --- a/miniprogram/app.ts +++ b/miniprogram/app.ts @@ -11,7 +11,7 @@ App({ */ api: { nextId: 1, - pool: [] + pool: new Set() }, /** @@ -24,6 +24,6 @@ App({ */ onLaunch() { Logger.log("小程序启动...", - LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLaunchLabel); + LevelLogLabel.InfoLabel, LifeCycleLogLabel.OnLaunchLabel); } }) \ No newline at end of file diff --git a/miniprogram/core/Api.ts b/miniprogram/core/Api.ts index 041df1b..44ad978 100644 --- a/miniprogram/core/Api.ts +++ b/miniprogram/core/Api.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "./EventEmitter"; import { LogLabel } from "./LogLabel"; import { Logger } from "./Logger"; -import { LevelLogLabel, colorRadio } from "./PresetLogLabel"; +import { LevelLogLabel, colorRadio, StatusLabel } from "./PresetLogLabel"; interface IAppAPIParam { api: { @@ -13,8 +13,9 @@ interface IAppAPIParam { /** * 请求池 + * 保存正在等待的 API 请求 */ - pool: API[]; + pool: Set>; } } @@ -78,6 +79,9 @@ type IParamSetting = { } } +type SuccessCallbackResult = WechatMiniprogram.RequestSuccessCallbackResult; +type GeneralCallbackResult = WechatMiniprogram.GeneralCallbackResult; + /** * API 事件 */ @@ -92,6 +96,26 @@ type IAPIEvent = { * 请求数据解析完成后 */ parseRequestData: Partial; + + /** + * 请求发送前 + */ + request: IWxRequestOption; + + /** + * 成功回调 + */ + success: SuccessCallbackResult; + + /** + * 失败回调 + */ + fail: GeneralCallbackResult; + + /** + * 完成回调 + */ + complete: GeneralCallbackResult; } /** @@ -104,7 +128,7 @@ class API extends EventEmitter extends EventEmitter { + Logger.logMultiple( + [LevelLogLabel.InfoLabel, this.LogLabel, StatusLabel.Pending], + `请求发送中: `, data + ); + }) + + this.on("success", (data) => { + Logger.logMultiple( + [LevelLogLabel.InfoLabel, this.LogLabel, StatusLabel.Success], + `请求成功: `, data + ); + }) + + this.on("fail", (data) => { + Logger.logMultiple( + [LevelLogLabel.ErrorLabel, this.LogLabel, StatusLabel.Failed], + `请求失败: `, data.errMsg + ); + }) } /** @@ -171,14 +218,14 @@ class API extends EventEmitter) { + public param(data?: Partial):this { this.data = data; if (this.data === void 0) { Logger.log(`数据初始化异常: 没有输入 [data] 数据!`, - LevelLogLabel.FatalLabel, this.LogLabel); - return; + LevelLogLabel.ErrorLabel, this.LogLabel); + return this; } for (let key in this.params) { @@ -194,7 +241,7 @@ class API extends EventEmitter extends EventEmitter extends EventEmitter = this.requestData = { url: API.baseUrl + this.url, @@ -274,7 +315,192 @@ class API extends EventEmitter(); + if (app.api.pool.has(this as any)) { + return this; + } + + // 获取标识符 + if (!this.id) { + this.id = app.api.nextId; + app.api.nextId ++; + } + + app.api.pool.add(this as any); + return this; + } + + /** + * 从 pool 中移除 + */ + protected removePool():this { + let app = getApp(); + app.api.pool.delete(this as any); + return this; + } + + /** + * 寻找相似的请求 + */ + protected findSameAPI():API | undefined { + + if (this.requestData === void 0) { + Logger.log(`搜索相似请求异常: 没有收集 [requestData] 数据!`, + LevelLogLabel.ErrorLabel, this.LogLabel); + return; + } + + let app = getApp(); + let sameAPI:API | undefined; + + // 判断 API 是否相似 + app.api.pool.forEach((api) => { + if (api === this) return; + if (!api.requestData) return; + if (api.requestData!.url !== this.requestData!.url) return; + if (api.requestData!.method !== this.requestData!.method) return; + sameAPI = api; + }); + + return sameAPI; + } + + /** + * 标记此实例是否已被使用 + */ + private isUsed = false; + + /** + * 请求策略 + */ + public policy:RequestPolicy = RequestPolicy.RequestAnyway; + + /** + * 运行 API + */ + public request():this { + + if (this.requestData === void 0) { + Logger.log(`请求发送异常: 没有收集 [requestData] 数据!`, + LevelLogLabel.ErrorLabel, this.LogLabel); + return this; + } + + if (this.isUsed) { + Logger.log(`请求发送异常: 此实例已经使用过了,请使用新实例操作`, + LevelLogLabel.ErrorLabel, this.LogLabel); + return this; + } else { + this.isUsed = true; + } + + // 加入请求池 + this.addPool(); + + // 发起请求 + let request = () => { + + // 触发请求发送事件 + this.emit("request", this.requestData!) + + wx.request({ + ...this.requestData!, + success: (e) => { + this.emit("success", e); + }, + fail: (e) => { + this.emit("fail", e); + }, + complete: (e) => { + this.emit("complete", e); + } + }); + } + + if (this.policy !== RequestPolicy.RequestAnyway) { + let lastAPI = this.findSameAPI(); + + if (lastAPI) { + + // 被上次请求阻止 + if (this.policy === RequestPolicy.BlockByLastRequest) { + return this; + } + + // 使用上次请求结果 + if (this.policy === RequestPolicy.useLastRequest) { + lastAPI.on("success", (e) => { + this.emit("success", e as SuccessCallbackResult); + this.emit("complete", {errMsg: e.errMsg}); + }); + lastAPI.on("fail", (e) => { + this.emit("fail", e); + this.emit("complete", {errMsg: e.errMsg}); + }); + } + + // 等待上次请求 + if (this.policy === RequestPolicy.waitLastRequest) { + lastAPI.on("success", () => request()); + lastAPI.on("fail", () => request()); + } + } + } else { + request(); + } + + // 监听请求完成后,从 pool 中移除,释放内存 + this.on("complete", () => { + this.removePool(); + }) + + return this; + } +} + +/** + * Request 请求策略 + * 此策略用于节流 + */ +enum RequestPolicy { + + /** + * 什么都不管,发就完了 + */ + RequestAnyway = 1, + + /** + * 如果存在等待中的相似请求 + * 等待相似请求结束后在发送 + */ + waitLastRequest = 2, + + /** + * 如果存在等待中的相似请求 + * 阻止本次请求发送 + * 将相似请求的结果作为本次请求结果 + */ + useLastRequest = 3, + + /** + * 如果存在等待中的相似请求 + * 阻止本次请求发送 + */ + BlockByLastRequest = 4 } /** diff --git a/miniprogram/core/EventEmitter.ts b/miniprogram/core/EventEmitter.ts index 34fb56d..b3fc67c 100644 --- a/miniprogram/core/EventEmitter.ts +++ b/miniprogram/core/EventEmitter.ts @@ -33,6 +33,14 @@ export class EventEmitter> { this.all = new Map(); } + public resetAll() { + this.all = new Map(); + } + + public reset(type: Key) { + this.all!.set(type, [] as EventHandlerList); + } + on(type: Key, handler: Handler): void; on(type: '*', handler: WildcardHandler): void; diff --git a/miniprogram/core/Module.ts b/miniprogram/core/Module.ts index e05192e..dfeed61 100644 --- a/miniprogram/core/Module.ts +++ b/miniprogram/core/Module.ts @@ -404,7 +404,7 @@ class Manager { if(data.length > 0) log += `Using Props: ${ data.join(", ") }\n`; if(func.length > 0) log += `Using Function: ${ func.join(", ") }\n`; - Logger.log(log, LevelLogLabel.TraceLabel, Manager.AddModuleLabel); + Logger.log(log, LevelLogLabel.InfoLabel, Manager.AddModuleLabel); } return res; diff --git a/miniprogram/core/PresetLogLabel.ts b/miniprogram/core/PresetLogLabel.ts index 2cad9c8..46d0daa 100644 --- a/miniprogram/core/PresetLogLabel.ts +++ b/miniprogram/core/PresetLogLabel.ts @@ -310,12 +310,37 @@ class LifeCycleLogLabel { ); } +class StatusLabel { + + /** + * 等待 + */ + static readonly Pending = new LogLabel( + "◉", new LogStyle().setBlank("0 2px").setBorder("1000px", "1px solid lightblue").setColor("lightblue") + ); + + /** + * 成功 + */ + static readonly Success = new LogLabel( + "√", new LogStyle().setBlank("0 4px").setBorder("1000px", "1px solid lightgreen").setColor("lightgreen") + ); + + /** + * 失败 + */ + static readonly Failed = new LogLabel( + "×", new LogStyle().setBlank("0 4px").setBorder("1000px", "1px solid red").setColor("red") + ); +} + const NormalStyle = StackLogLabel.normalStyle; export { NormalStyle, StackInfo, - StackLogLabel, + StackLogLabel, + StatusLabel, LevelLogLabel, LifeCycleLogLabel, normalLifeStyleGen as colorRadio, diff --git a/miniprogram/core/Storage.ts b/miniprogram/core/Storage.ts index ca1a0fb..7fc07cf 100644 --- a/miniprogram/core/Storage.ts +++ b/miniprogram/core/Storage.ts @@ -131,7 +131,7 @@ class Storage { success: (data) => { Logger.log(`数据保存成功! errMsg: ${ data.errMsg }`, - LevelLogLabel.TraceLabel, this.StorageLogLabel); + LevelLogLabel.InfoLabel, this.StorageLogLabel); }, fail: (data) => { diff --git a/miniprogram/pages/Timetable/StatusBar.ts b/miniprogram/pages/Timetable/StatusBar.ts index 70a776f..1a9812d 100644 --- a/miniprogram/pages/Timetable/StatusBar.ts +++ b/miniprogram/pages/Timetable/StatusBar.ts @@ -101,14 +101,14 @@ implements Partial { Logger.log(`计算并设置 StatusBar 的高度为: ${ barHeight + 4 }px, ` + `状态栏高度: ${ statusBarHeight }px, 胶囊占位: ${ capsule }px`, - LevelLogLabel.DebugLabel, StatusBar.StatusBarLabel); + LevelLogLabel.InfoLabel, StatusBar.StatusBarLabel); } public onLoad() { Logger.log("StatusBar 模块加载...", - LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLoadLabel, StatusBar.StatusBarLabel); + LevelLogLabel.InfoLabel, LifeCycleLogLabel.OnLoadLabel, StatusBar.StatusBarLabel); this.setHeight(); } diff --git a/miniprogram/pages/Timetable/TestCore.ts b/miniprogram/pages/Timetable/TestCore.ts index 2ebf306..94d768c 100644 --- a/miniprogram/pages/Timetable/TestCore.ts +++ b/miniprogram/pages/Timetable/TestCore.ts @@ -28,8 +28,6 @@ implements Partial { } class TestApi extends API { - - public override key:string = "TestApi"; public override params: IParamSetting = { name: { @@ -44,17 +42,7 @@ implements Partial { public constructor() { super(); - this.initLabel(); - - this.emit("initData", {}) - - this.on("initData", (d) => { - - }) - - this.on("parseRequestData", (data) => { - console.log("parseRequestData", data) - }) + this.initLabel("TestApi"); } } @@ -65,8 +53,7 @@ implements Partial { info: { data: "abc" } - }); - console.log(api); + }).request(); } }