Add API Module! #13

Merged
MrKBear merged 2 commits from dev-mrkbear into master 2021-12-31 11:24:28 +08:00
8 changed files with 284 additions and 38 deletions

View File

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

View File

@ -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<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
*/
@ -92,6 +96,26 @@ type IAPIEvent<I extends IAnyData, O extends IAnyData> = {
*
*/
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: 这里可能涉及负载均衡
*/
public static get baseUrl():string {
return "https://xxx.xxx";
return "https://blog.mrkbear.com";
}
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(
`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
* @param data API需要的全部数据
*/
public param(data?: Partial<I>) {
public param(data?: Partial<I>):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<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
// 数据存在测试
if (data === void 0 && !Optional) {
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!);
} else {
Logger.logMultiple(
[LevelLogLabel.FatalLabel, this.LogLabel],
[LevelLogLabel.ErrorLabel, this.LogLabel],
`数据校验异常: [${ key }] 参数存在未知类型的 tester:`, tester
);
}
if (!testRes) {
Logger.logMultiple(
[LevelLogLabel.FatalLabel, this.LogLabel],
[LevelLogLabel.ErrorLabel, this.LogLabel],
`数据校验异常: [${ key }] 参数数据未通过自定义的 tester:`, data
);
}
@ -226,12 +273,6 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
// 触发数据初始化事件
this.emit("initData", this.data);
if (this.data === void 0) {
Logger.log(`收集请求数据异常: 没有输入 [data] 数据!`,
LevelLogLabel.FatalLabel, this.LogLabel);
return;
}
// 重置请求数据
const requestData:IWxRequestOption<O> = this.requestData = {
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();
}
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(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(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;

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;
export {
NormalStyle,
StackInfo,
StackLogLabel,
StackLogLabel,
StatusLabel,
LevelLogLabel,
LifeCycleLogLabel,
normalLifeStyleGen as colorRadio,

View File

@ -131,7 +131,7 @@ class Storage<T extends IStorageData> {
success: (data) => {
Logger.log(`数据保存成功! errMsg: ${ data.errMsg }`,
LevelLogLabel.TraceLabel, this.StorageLogLabel);
LevelLogLabel.InfoLabel, this.StorageLogLabel);
},
fail: (data) => {

View File

@ -101,14 +101,14 @@ implements Partial<ILifetime> {
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();
}

View File

@ -28,8 +28,6 @@ implements Partial<ILifetime> {
}
class TestApi extends API<ITestApiInput, {}> {
public override key:string = "TestApi";
public override params: IParamSetting<ITestApiInput> = {
name: {
@ -44,17 +42,7 @@ implements Partial<ILifetime> {
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<ILifetime> {
info: {
data: "abc"
}
});
console.log(api);
}).request();
}
}