Merge pull request 'Add API Module!' (#13) from dev-mrkbear into master

Reviewed-on: http://git.mrkbear.com/MrKBear/mini-dlpu-v3/pulls/13
This commit is contained in:
MrKBear 2021-12-31 11:24:27 +08:00
commit b37977418a
8 changed files with 284 additions and 38 deletions

View File

@ -11,7 +11,7 @@ App<IAppAPIParam>({
*/ */
api: { api: {
nextId: 1, nextId: 1,
pool: [] pool: new Set()
}, },
/** /**
@ -24,6 +24,6 @@ App<IAppAPIParam>({
*/ */
onLaunch() { onLaunch() {
Logger.log("小程序启动...", Logger.log("小程序启动...",
LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLaunchLabel); LevelLogLabel.InfoLabel, LifeCycleLogLabel.OnLaunchLabel);
} }
}) })

View File

@ -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: {
@ -13,8 +13,9 @@ interface IAppAPIParam {
/** /**
* *
* API
*/ */
pool: API<IAnyData, IAnyData>[]; pool: Set<API<IAnyData, IAnyData>>;
} }
} }
@ -78,6 +79,9 @@ type IParamSetting<T extends IAnyData> = {
} }
} }
type SuccessCallbackResult<O extends IAnyData> = WechatMiniprogram.RequestSuccessCallbackResult<O>;
type GeneralCallbackResult = WechatMiniprogram.GeneralCallbackResult;
/** /**
* API * API
*/ */
@ -92,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;
} }
/** /**
@ -104,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(
@ -160,10 +184,33 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
/** /**
* *
*/ */
public initLabel() { public initLabel(key: string) {
this.key = key;
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
);
})
} }
/** /**
@ -171,14 +218,14 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
* data * data
* @param data API需要的全部数据 * @param data API需要的全部数据
*/ */
public param(data?: Partial<I>) { public param(data?: Partial<I>):this {
this.data = data; this.data = data;
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; return this;
} }
for (let key in this.params) { for (let key in this.params) {
@ -194,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);
} }
// 用户自定义测试 // 用户自定义测试
@ -209,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
); );
} }
@ -226,12 +273,6 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
// 触发数据初始化事件 // 触发数据初始化事件
this.emit("initData", this.data); this.emit("initData", this.data);
if (this.data === void 0) {
Logger.log(`收集请求数据异常: 没有输入 [data] 数据!`,
LevelLogLabel.FatalLabel, this.LogLabel);
return;
}
// 重置请求数据 // 重置请求数据
const requestData:IWxRequestOption<O> = this.requestData = { const requestData:IWxRequestOption<O> = this.requestData = {
url: API.baseUrl + this.url, url: API.baseUrl + this.url,
@ -274,7 +315,192 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
} }
} }
} }
return this;
} }
/**
*
*/
protected id:number = 0;
/**
*
*/
protected addPool():this {
let app = getApp<IAppAPIParam>();
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<IAppAPIParam>();
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
*/
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<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
} }
/** /**

View File

@ -33,6 +33,14 @@ export class EventEmitter<Events extends Record<EventType, unknown>> {
this.all = new Map(); this.all = new Map();
} }
public resetAll() {
this.all = new Map();
}
public reset<Key extends keyof Events>(type: Key) {
this.all!.set(type, [] as EventHandlerList<Events[keyof Events]>);
}
on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void; on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
on(type: '*', handler: WildcardHandler<Events>): void; on(type: '*', handler: WildcardHandler<Events>): void;

View File

@ -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;

View File

@ -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,

View File

@ -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) => {

View File

@ -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();
} }

View File

@ -29,8 +29,6 @@ implements Partial<ILifetime> {
class TestApi extends API<ITestApiInput, {}> { class TestApi extends API<ITestApiInput, {}> {
public override key:string = "TestApi";
public override params: IParamSetting<ITestApiInput> = { public override params: IParamSetting<ITestApiInput> = {
name: { name: {
tester: "123", tester: "123",
@ -44,17 +42,7 @@ implements Partial<ILifetime> {
public constructor() { public constructor() {
super(); super();
this.initLabel(); this.initLabel("TestApi");
this.emit("initData", {})
this.on("initData", (d) => {
})
this.on("parseRequestData", (data) => {
console.log("parseRequestData", data)
})
} }
} }
@ -65,8 +53,7 @@ implements Partial<ILifetime> {
info: { info: {
data: "abc" data: "abc"
} }
}); }).request();
console.log(api);
} }
} }