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:
commit
b37977418a
@ -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);
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,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: {
|
||||||
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user