Add API Module!
This commit is contained in:
		
							parent
							
								
									af68984caa
								
							
						
					
					
						commit
						7a78cf0594
					
				| @ -24,6 +24,6 @@ App<IAppAPIParam>({ | |||||||
|      */ |      */ | ||||||
|     onLaunch() { |     onLaunch() { | ||||||
|         Logger.log("小程序启动...",  |         Logger.log("小程序启动...",  | ||||||
|         LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLaunchLabel); |         LevelLogLabel.InfoLabel, LifeCycleLogLabel.OnLaunchLabel); | ||||||
|     } |     } | ||||||
| }) | }) | ||||||
| @ -1,7 +1,7 @@ | |||||||
| import { EventEmitter } from "./EventEmitter"; | import { EventEmitter } from "./EventEmitter"; | ||||||
| import { LogLabel } from "./LogLabel"; | import { LogLabel } from "./LogLabel"; | ||||||
| import { Logger } from "./Logger"; | import { Logger } from "./Logger"; | ||||||
| import { LevelLogLabel, colorRadio } from "./PresetLogLabel"; | import { LevelLogLabel, colorRadio, StatusLabel } from "./PresetLogLabel"; | ||||||
| 
 | 
 | ||||||
| interface IAppAPIParam { | interface IAppAPIParam { | ||||||
|     api: { |     api: { | ||||||
| @ -79,6 +79,9 @@ type IParamSetting<T extends IAnyData> = { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type SuccessCallbackResult<O extends IAnyData> = WechatMiniprogram.RequestSuccessCallbackResult<O>; | ||||||
|  | type GeneralCallbackResult = WechatMiniprogram.GeneralCallbackResult; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * API 事件 |  * API 事件 | ||||||
|  */ |  */ | ||||||
| @ -93,6 +96,26 @@ type IAPIEvent<I extends IAnyData, O extends IAnyData> = { | |||||||
|      * 请求数据解析完成后 |      * 请求数据解析完成后 | ||||||
|      */ |      */ | ||||||
|     parseRequestData: Partial<I>; |     parseRequestData: Partial<I>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 请求发送前 | ||||||
|  |      */ | ||||||
|  |     request: IWxRequestOption<O>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 成功回调 | ||||||
|  |      */ | ||||||
|  |     success: SuccessCallbackResult<O>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 失败回调 | ||||||
|  |      */ | ||||||
|  |     fail: GeneralCallbackResult; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 完成回调 | ||||||
|  |      */ | ||||||
|  |     complete: GeneralCallbackResult; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -105,7 +128,7 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
|      * TODO: 这里可能涉及负载均衡 |      * TODO: 这里可能涉及负载均衡 | ||||||
|      */ |      */ | ||||||
|     public static get baseUrl():string { |     public static get baseUrl():string { | ||||||
|         return "https://xxx.xxx"; |         return "https://blog.mrkbear.com"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static defaultLogLabel:LogLabel = new LogLabel( |     public static defaultLogLabel:LogLabel = new LogLabel( | ||||||
| @ -166,6 +189,28 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
|         this.LogLabel = new LogLabel( |         this.LogLabel = new LogLabel( | ||||||
|             `API:${ this.key }`, colorRadio(200, 120, 222) |             `API:${ this.key }`, colorRadio(200, 120, 222) | ||||||
|         ); |         ); | ||||||
|  | 
 | ||||||
|  |         // 添加 API 生命周期调试事件
 | ||||||
|  |         this.on("request", (data) => { | ||||||
|  |             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 | ||||||
|  |             ); | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -179,7 +224,7 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
| 
 | 
 | ||||||
|         if (this.data === void 0) { |         if (this.data === void 0) { | ||||||
|             Logger.log(`数据初始化异常: 没有输入 [data] 数据!`,  |             Logger.log(`数据初始化异常: 没有输入 [data] 数据!`,  | ||||||
|             LevelLogLabel.FatalLabel, this.LogLabel); |             LevelLogLabel.ErrorLabel, this.LogLabel); | ||||||
|             return this; |             return this; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -196,7 +241,7 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
|             // 数据存在测试
 |             // 数据存在测试
 | ||||||
|             if (data === void 0 && !Optional) { |             if (data === void 0 && !Optional) { | ||||||
|                 Logger.log(`数据校验异常: 数据 [${key}] 是必须的,但是并没有接收到!`,  |                 Logger.log(`数据校验异常: 数据 [${key}] 是必须的,但是并没有接收到!`,  | ||||||
|                 LevelLogLabel.FatalLabel, this.LogLabel); |                 LevelLogLabel.ErrorLabel, this.LogLabel); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // 用户自定义测试
 |             // 用户自定义测试
 | ||||||
| @ -211,14 +256,14 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
|                     testRes = tester(data!); |                     testRes = tester(data!); | ||||||
|                 } else { |                 } else { | ||||||
|                     Logger.logMultiple( |                     Logger.logMultiple( | ||||||
|                         [LevelLogLabel.FatalLabel, this.LogLabel], |                         [LevelLogLabel.ErrorLabel, this.LogLabel], | ||||||
|                         `数据校验异常: [${ key }] 参数存在未知类型的 tester:`, tester |                         `数据校验异常: [${ key }] 参数存在未知类型的 tester:`, tester | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if (!testRes) { |                 if (!testRes) { | ||||||
|                     Logger.logMultiple( |                     Logger.logMultiple( | ||||||
|                         [LevelLogLabel.FatalLabel, this.LogLabel], |                         [LevelLogLabel.ErrorLabel, this.LogLabel], | ||||||
|                         `数据校验异常: [${ key }] 参数数据未通过自定义的 tester:`, data |                         `数据校验异常: [${ key }] 参数数据未通过自定义的 tester:`, data | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
| @ -282,9 +327,12 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
|     /** |     /** | ||||||
|      * 将此请求加入到请求池 |      * 将此请求加入到请求池 | ||||||
|      */ |      */ | ||||||
|     protected addPool() { |     protected addPool():this { | ||||||
|          |          | ||||||
|         let app = getApp<IAppAPIParam>(); |         let app = getApp<IAppAPIParam>(); | ||||||
|  |         if (app.api.pool.has(this as any)) { | ||||||
|  |             return this; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // 获取标识符
 |         // 获取标识符
 | ||||||
|         if (!this.id) { |         if (!this.id) { | ||||||
| @ -293,22 +341,166 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         app.api.pool.add(this as any); |         app.api.pool.add(this as any); | ||||||
|  |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 从 pool 中移除 |      * 从 pool 中移除 | ||||||
|      */ |      */ | ||||||
|     protected removePool() { |     protected removePool():this { | ||||||
|         let app = getApp<IAppAPIParam>(); |         let app = getApp<IAppAPIParam>(); | ||||||
|         app.api.pool.delete(this as any); |         app.api.pool.delete(this as any); | ||||||
|  |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 寻找相似的请求 | ||||||
|  |      */ | ||||||
|  |     protected findSameAPI():API<IAnyData, IAnyData> | undefined { | ||||||
|  | 
 | ||||||
|  |         if (this.requestData === void 0) { | ||||||
|  |             Logger.log(`搜索相似请求异常: 没有收集 [requestData] 数据!`,  | ||||||
|  |             LevelLogLabel.ErrorLabel, this.LogLabel); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let app = getApp<IAppAPIParam>(); | ||||||
|  |         let sameAPI:API<IAnyData, IAnyData> | 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 |      * 运行 API | ||||||
|      */ |      */ | ||||||
|     public run() { |     public request():this { | ||||||
|         this.addPool(); | 
 | ||||||
|  |         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<O>({ | ||||||
|  |                 ...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<O>); | ||||||
|  |                         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 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -404,7 +404,7 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> { | |||||||
|             if(data.length > 0) log += `Using Props: ${ data.join(", ") }\n`; |             if(data.length > 0) log += `Using Props: ${ data.join(", ") }\n`; | ||||||
|             if(func.length > 0) log += `Using Function: ${ func.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; |         return res; | ||||||
|  | |||||||
| @ -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; | const NormalStyle = StackLogLabel.normalStyle; | ||||||
| 
 | 
 | ||||||
| export {  | export {  | ||||||
|     NormalStyle, |     NormalStyle, | ||||||
|     StackInfo,  |     StackInfo,  | ||||||
|     StackLogLabel, |     StackLogLabel, | ||||||
|  |     StatusLabel,  | ||||||
|     LevelLogLabel,  |     LevelLogLabel,  | ||||||
|     LifeCycleLogLabel,  |     LifeCycleLogLabel,  | ||||||
|     normalLifeStyleGen as colorRadio, |     normalLifeStyleGen as colorRadio, | ||||||
|  | |||||||
| @ -131,7 +131,7 @@ class Storage<T extends IStorageData> { | |||||||
| 
 | 
 | ||||||
|                 success: (data) => { |                 success: (data) => { | ||||||
|                     Logger.log(`数据保存成功! errMsg: ${ data.errMsg }`,  |                     Logger.log(`数据保存成功! errMsg: ${ data.errMsg }`,  | ||||||
|                     LevelLogLabel.TraceLabel, this.StorageLogLabel); |                     LevelLogLabel.InfoLabel, this.StorageLogLabel); | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 fail: (data) => { |                 fail: (data) => { | ||||||
|  | |||||||
| @ -101,14 +101,14 @@ implements Partial<ILifetime> { | |||||||
| 
 | 
 | ||||||
|         Logger.log(`计算并设置 StatusBar 的高度为: ${ barHeight + 4 }px, ` + |         Logger.log(`计算并设置 StatusBar 的高度为: ${ barHeight + 4 }px, ` + | ||||||
|         `状态栏高度: ${ statusBarHeight }px, 胶囊占位: ${ capsule }px`,  |         `状态栏高度: ${ statusBarHeight }px, 胶囊占位: ${ capsule }px`,  | ||||||
|         LevelLogLabel.DebugLabel, StatusBar.StatusBarLabel); |         LevelLogLabel.InfoLabel, StatusBar.StatusBarLabel); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public onLoad() { |     public onLoad() { | ||||||
|          |          | ||||||
|         Logger.log("StatusBar 模块加载...",  |         Logger.log("StatusBar 模块加载...",  | ||||||
|         LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLoadLabel, StatusBar.StatusBarLabel); |         LevelLogLabel.InfoLabel, LifeCycleLogLabel.OnLoadLabel, StatusBar.StatusBarLabel); | ||||||
| 
 | 
 | ||||||
|         this.setHeight(); |         this.setHeight(); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -43,16 +43,6 @@ implements Partial<ILifetime> { | |||||||
|             public constructor() { |             public constructor() { | ||||||
|                 super(); |                 super(); | ||||||
|                 this.initLabel("TestApi"); |                 this.initLabel("TestApi"); | ||||||
| 
 |  | ||||||
|                 this.emit("initData", {}) |  | ||||||
| 
 |  | ||||||
|                 this.on("initData", (d) => { |  | ||||||
| 
 |  | ||||||
|                 }) |  | ||||||
| 
 |  | ||||||
|                 this.on("parseRequestData", (data) => { |  | ||||||
|                     console.log("parseRequestData", data) |  | ||||||
|                 }) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -63,8 +53,7 @@ implements Partial<ILifetime> { | |||||||
|             info: { |             info: { | ||||||
|                 data: "abc" |                 data: "abc" | ||||||
|             } |             } | ||||||
|         }).run(); |         }).request(); | ||||||
|         console.log(api); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user