Add API Module! #13
@ -24,6 +24,6 @@ App<IAppAPIParam>({
|
||||
*/
|
||||
onLaunch() {
|
||||
Logger.log("小程序启动...",
|
||||
LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLaunchLabel);
|
||||
LevelLogLabel.InfoLabel, LifeCycleLogLabel.OnLaunchLabel);
|
||||
}
|
||||
})
|
@ -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: {
|
||||
@ -79,6 +79,9 @@ type IParamSetting<T extends IAnyData> = {
|
||||
}
|
||||
}
|
||||
|
||||
type SuccessCallbackResult<O extends IAnyData> = WechatMiniprogram.RequestSuccessCallbackResult<O>;
|
||||
type GeneralCallbackResult = WechatMiniprogram.GeneralCallbackResult;
|
||||
|
||||
/**
|
||||
* API 事件
|
||||
*/
|
||||
@ -93,6 +96,26 @@ type IAPIEvent<I extends IAnyData, O extends IAnyData> = {
|
||||
* 请求数据解析完成后
|
||||
*/
|
||||
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: 这里可能涉及负载均衡
|
||||
*/
|
||||
public static get baseUrl():string {
|
||||
return "https://xxx.xxx";
|
||||
return "https://blog.mrkbear.com";
|
||||
}
|
||||
|
||||
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(
|
||||
`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) {
|
||||
Logger.log(`数据初始化异常: 没有输入 [data] 数据!`,
|
||||
LevelLogLabel.FatalLabel, this.LogLabel);
|
||||
LevelLogLabel.ErrorLabel, this.LogLabel);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -196,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);
|
||||
}
|
||||
|
||||
// 用户自定义测试
|
||||
@ -211,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
|
||||
);
|
||||
}
|
||||
@ -282,9 +327,12 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
|
||||
/**
|
||||
* 将此请求加入到请求池
|
||||
*/
|
||||
protected addPool() {
|
||||
protected addPool():this {
|
||||
|
||||
let app = getApp<IAppAPIParam>();
|
||||
if (app.api.pool.has(this as any)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// 获取标识符
|
||||
if (!this.id) {
|
||||
@ -293,24 +341,168 @@ class API<I extends IAnyData, O extends IAnyData> extends EventEmitter<IAPIEvent
|
||||
}
|
||||
|
||||
app.api.pool.add(this as any);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 pool 中移除
|
||||
*/
|
||||
protected removePool() {
|
||||
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 run() {
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP 请求类型
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -43,16 +43,6 @@ implements Partial<ILifetime> {
|
||||
public constructor() {
|
||||
super();
|
||||
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: {
|
||||
data: "abc"
|
||||
}
|
||||
}).run();
|
||||
console.log(api);
|
||||
}).request();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user