Merge pull request 'Optimize Storage Modular' (#16) from dev-mrkbear into master

Reviewed-on: http://git.mrkbear.com/MrKBear/mini-dlpu-v3/pulls/16
This commit is contained in:
MrKBear 2022-01-03 13:36:55 +08:00
commit de67ab0d68
8 changed files with 269 additions and 373 deletions

View File

@ -2,9 +2,9 @@
掌上教务处作为工业大学的社区开源项目自从2017年开始已有近5年岁月在无数同学的贡献之下为大家打造便捷的校园服务。
__*!!!注意!!!*__
__*!!!警告!!!*__
请在主仓库提交代码,而非镜像仓库!
请在主仓库提交代码,而非镜像仓库!在镜像仓库提交的代码将会在同步时被覆盖!
主仓库: http://git.mrkbear.com/MrKBear/mini-dlpu-v3

View File

@ -1,8 +1,9 @@
import { IAppAPIParam } from "./core/Api";
import { IAppStorageParam, Storage, IStorageData } from "./core/Storage";
import { Logger, LevelLogLabel, LifeCycleLogLabel } from "./core/Logger";
App<IAppAPIParam>({
App<IAppAPIParam & IAppStorageParam>({
/**
* API
@ -16,7 +17,7 @@ App<IAppAPIParam>({
/**
*
*/
// storageCache: new Set<string>(),
storage: new Map<string, Storage<IStorageData>>(),
/**
*

View File

@ -2,27 +2,18 @@ export type EventType = string | symbol;
// An event handler can take an optional event argument
// and should not return a value
export type Handler<T = unknown> = (event: T) => void;
export type WildcardHandler<T = Record<string, unknown>> = (
type: keyof T,
event: T[keyof T]
) => void;
export type Handler<T = any> = (event: T) => void;
// An array of all currently registered event handlers for a type
export type EventHandlerList<T = unknown> = Array<Handler<T>>;
export type WildCardEventHandlerList<T = Record<string, unknown>> = Array<WildcardHandler<T>>;
export type EventHandlerList<T = any> = Array<Handler<T>>;
// A map of event types and their corresponding event handlers.
export type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<
keyof Events | '*',
EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>
export type EventHandlerMap<Events extends Record<EventType, any>> = Map<
keyof Events,
EventHandlerList<Events[keyof Events]>
>;
type GenericEventHandler<Events extends Record<EventType, unknown>> =
| Handler<Events[keyof Events]>
| WildcardHandler<Events>;
export class Emitter<Events extends Record<EventType, unknown>> {
export class Emitter<Events extends Record<EventType, any>> {
/**
* A Map of event names to registered handler functions.
@ -41,17 +32,14 @@ export class Emitter<Events extends Record<EventType, unknown>> {
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;
/**
* Register an event handler for the given type.
* @param {string|symbol} type Type of event to listen for, or `'*'` for all events
* @param {string|symbol} type Type of event to listen for
* @param {Function} handler Function to call in response to given event
* @memberOf mitt
*/
public on<Key extends keyof Events>(type: Key, handler: GenericEventHandler<Events>) {
const handlers: Array<GenericEventHandler<Events>> | undefined = this.all!.get(type);
public on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>) {
const handlers: Array<Handler<Events[Key]>> | undefined = this.all!.get(type);
if (handlers) {
handlers.push(handler);
}
@ -60,18 +48,15 @@ export class Emitter<Events extends Record<EventType, unknown>> {
}
}
off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): void;
off(type: '*', handler: WildcardHandler<Events>): void;
/**
* Remove an event handler for the given type.
* If `handler` is omitted, all handlers of the given type are removed.
* @param {string|symbol} type Type of event to unregister `handler` from, or `'*'`
* @param {string|symbol} type Type of event to unregister `handler` from
* @param {Function} [handler] Handler function to remove
* @memberOf mitt
*/
public off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler<Events>) {
const handlers: Array<GenericEventHandler<Events>> | undefined = this.all!.get(type);
public off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>) {
const handlers: Array<Handler<Events[Key]>> | undefined = this.all!.get(type);
if (handlers) {
if (handler) {
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
@ -82,20 +67,14 @@ export class Emitter<Events extends Record<EventType, unknown>> {
}
}
emit<Key extends keyof Events>(type: Key, event: Events[Key]): void;
emit<Key extends keyof Events>(type: undefined extends Events[Key] ? Key : never): void;
/**
* Invoke all handlers for the given type.
* If present, `'*'` handlers are invoked after type-matched handlers.
*
* Note: Manually firing '*' handlers is not supported.
*
* @param {string|symbol} type The event type to invoke
* @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
* @memberOf mitt
*/
emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
emit<Key extends keyof Events>(type: Key, evt: Events[Key]) {
let handlers = this.all!.get(type);
if (handlers) {
(handlers as EventHandlerList<Events[keyof Events]>)
@ -104,14 +83,5 @@ export class Emitter<Events extends Record<EventType, unknown>> {
handler(evt!);
});
}
handlers = this.all!.get('*');
if (handlers) {
(handlers as WildCardEventHandlerList<Events>)
.slice()
.map((handler) => {
handler(type, evt!);
});
}
}
}

View File

@ -1,5 +1,5 @@
import { Emitter, EventType } from "./Emitter";
import { Logger, LogLabel, LogStyle, LevelLogLabel } from "./Logger";
import { Emitter } from "./Emitter";
import { Logger, LogLabel, colorRadio, LevelLogLabel } from "./Logger";
/**
*
@ -50,6 +50,149 @@ type Depends<M extends Manager<AnyWXContext>> = {
[x:string]: Modular<M, Depends<M>>;
};
/**
*
*/
class WXInstanceMethods<
E extends IAnyTypeObject = IAnyTypeObject,
W extends AnyWXContext = AnyWXContext
>
extends Emitter<E>
implements InstanceMethods<W["data"]> {
public superContext: W;
public constructor(context: W) {
super();
this.superContext = context;
}
public setData(data: Partial<W["data"]> & WechatMiniprogram.IAnyObject, callback?: () => void): void {
return this.superContext.setData(data, callback);
}
public hasBehavior(behavior: string): void {
return this.superContext.hasBehavior(behavior);
}
public triggerEvent<DetailType = any>(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption): void {
return this.superContext.triggerEvent(name, detail, options)
}
public createSelectorQuery(): WechatMiniprogram.SelectorQuery {
return this.superContext.createSelectorQuery();
}
public createIntersectionObserver(options: WechatMiniprogram.CreateIntersectionObserverOption): WechatMiniprogram.IntersectionObserver {
return this.superContext.createIntersectionObserver(options);
}
public selectComponent(selector: string): WechatMiniprogram.Component.TrivialInstance {
return this.superContext.selectComponent(selector);
}
public selectAllComponents(selector: string): WechatMiniprogram.Component.TrivialInstance[] {
return this.superContext.selectAllComponents(selector);
}
public selectOwnerComponent(): WechatMiniprogram.Component.TrivialInstance {
return this.superContext.selectOwnerComponent();
}
public getRelationNodes(relationKey: string): WechatMiniprogram.Component.TrivialInstance[] {
return this.superContext.getRelationNodes(relationKey);
}
public groupSetData(callback?: () => void): void {
return this.superContext.groupSetData(callback);
}
public getTabBar(): WechatMiniprogram.Component.TrivialInstance {
return this.superContext.getTabBar();
}
public getPageId(): string {
return this.superContext.getPageId();
}
public animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[], duration: number, callback?: () => void): void;
public animate(selector: string, keyFrames: WechatMiniprogram.Component.ScrollTimelineKeyframe[], duration: number,
scrollTimeline: WechatMiniprogram.Component.ScrollTimelineOption): void;
public animate(selector: any, keyFrames: any, duration: any, scrollTimeline?: any): void {
return this.superContext.animate(selector, keyFrames, duration, scrollTimeline);
}
public clearAnimation(selector: string, callback: () => void): void;
public clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions, callback?: () => void): void;
public clearAnimation(selector: any, options?: any, callback?: any): void {
return this.superContext.clearAnimation(selector, options, callback);
}
public getOpenerEventChannel(): WechatMiniprogram.EventChannel {
return this.superContext.getOpenerEventChannel();
}
}
/**
*
*/
class WXInstanceProperties<
E extends IAnyTypeObject = IAnyTypeObject,
W extends AnyWXContext = AnyWXContext
>
extends WXInstanceMethods<E, W>
implements InstanceProperties {
public override superContext: W;
constructor(context: W) {
super(context);
this.superContext = context;
}
public get is(): string { return this.superContext.is };
public get route(): string { return this.superContext.route };
public get options(): Record<string, string | undefined> { return this.superContext.options };
}
class WXILifetime<
E extends IAnyTypeObject = IAnyTypeObject,
W extends AnyWXContext = AnyWXContext
>
extends WXInstanceProperties<E, W>
implements ILifetime {
public onLoad(query: Record<string, string | undefined>): void | Promise<void> {};
public onShow(): void | Promise<void> {};
public onReady(): void | Promise<void> {};
public onHide(): void | Promise<void> {};
public onUnload(): void | Promise<void> {};
public onPullDownRefresh(): void | Promise<void> {};
public onReachBottom(): void | Promise<void> {};
public onShareAppMessage(options: WechatMiniprogram.Page.IShareAppMessageOption): void | WechatMiniprogram.Page.ICustomShareContent {};
public onShareTimeline(): void | WechatMiniprogram.Page.ICustomTimelineContent {};
public onPageScroll(options: WechatMiniprogram.Page.IPageScrollOption): void | Promise<void> {};
public onTabItemTap(options: WechatMiniprogram.Page.ITabItemTapOption): void | Promise<void> {};
public onResize(options: WechatMiniprogram.Page.IResizeOption): void | Promise<void> {};
public onAddToFavorites(options: WechatMiniprogram.Page.IAddToFavoritesOption): WechatMiniprogram.Page.IAddToFavoritesContent {
return {};
};
}
/**
*
* @template M Manager
@ -60,9 +203,10 @@ type Depends<M extends Manager<AnyWXContext>> = {
class Modular<
M extends Manager<AnyWXContext> = Manager<AnyWXContext>,
DEP extends Depends<M> = Depends<M>,
E extends Record<EventType, unknown> = Record<EventType, unknown>,
TD extends IAnyTypeObject = IAnyTypeObject>
extends Emitter<E>
E extends IAnyTypeObject = IAnyTypeObject,
TD extends IAnyTypeObject = IAnyTypeObject
>
extends WXILifetime<E, M["context"]>
implements WXContext<TD, IAnyTypeObject> {
// [x:string]: any;
@ -95,7 +239,7 @@ implements WXContext<TD, IAnyTypeObject> {
public functionList:Set<string>;
/**
* 使
* 使
*/
public paramList:Set<string>;
@ -103,13 +247,6 @@ implements WXContext<TD, IAnyTypeObject> {
*
*/
public nameSpace:string;
// 映射主上下文属性
public get is():string { return this.context.is };
public get route():string { return this.context.route };
public get options():Record<string, string | undefined> {
return this.context.options;
};
/**
*
@ -120,7 +257,7 @@ implements WXContext<TD, IAnyTypeObject> {
*/
public constructor(manager:M, nameSpace:string, depend?: DEP) {
super();
super(manager.context);
// 保存微信上下文
this.manager = manager;
@ -134,7 +271,7 @@ implements WXContext<TD, IAnyTypeObject> {
this.nameSpace = nameSpace;
}
public setData(data:Partial<TD>, callback?: () => void):void {
public override setData(data:Partial<TD>, callback?: () => void):void {
if(this.data === void 0) {
this.data = {} as TD;
@ -162,76 +299,6 @@ implements WXContext<TD, IAnyTypeObject> {
(this.context as IAnyTypeObject)
[`${ this.nameSpace }$${ name }`] = fn.bind(this);
}
//#region 映射微信的继承函数
public hasBehavior(behavior: string): void {
return this.context.hasBehavior(behavior);
}
public triggerEvent<DetailType>(name: string, detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption): void {
return this.context.triggerEvent<DetailType>(name, detail, options);
}
public createSelectorQuery(): WechatMiniprogram.SelectorQuery {
return this.context.createSelectorQuery();
}
public createIntersectionObserver(options: WechatMiniprogram.CreateIntersectionObserverOption):
WechatMiniprogram.IntersectionObserver {
return this.context.createIntersectionObserver(options);
}
public selectComponent(selector: string): WechatMiniprogram.Component.TrivialInstance {
return this.context.selectComponent(selector);
}
public selectAllComponents(selector: string): WechatMiniprogram.Component.TrivialInstance[] {
return this.context.selectAllComponents(selector);
}
public selectOwnerComponent(): WechatMiniprogram.Component.TrivialInstance {
return this.context.selectOwnerComponent();
}
public getRelationNodes(relationKey: string): WechatMiniprogram.Component.TrivialInstance[] {
return this.context.getRelationNodes(relationKey);
}
public groupSetData(callback?: () => void): void {
return this.context.groupSetData(callback);
}
public getTabBar(): WechatMiniprogram.Component.TrivialInstance {
return this.context.getTabBar();
}
public getPageId(): string {
return this.context.getPageId();
}
public animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[],
duration: number, callback?: () => void): void;
public animate(selector: string, keyFrames: WechatMiniprogram.Component.ScrollTimelineKeyframe[],
duration: number, scrollTimeline: WechatMiniprogram.Component.ScrollTimelineOption): void;
public animate(selector: any, keyFrames: any, duration: any, scrollTimeline?: any): void {
return this.context.animate(selector, keyFrames, duration, scrollTimeline);
}
public clearAnimation(selector: string, callback: () => void): void;
public clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions,
callback?: () => void): void;
public clearAnimation(selector: any, options?: any, callback?: any): void {
return this.context.clearAnimation(selector, options, callback);
}
public getOpenerEventChannel(): WechatMiniprogram.EventChannel {
return this.context.getOpenerEventChannel();
}
//#endregion
}
/**
@ -244,19 +311,9 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
*
*/
static readonly WxLifeCycle:(keyof ILifetime)[] = [
"onShow",
"onReady",
"onHide",
"onUnload",
"onPullDownRefresh",
"onReachBottom",
"onShareAppMessage",
"onShareTimeline",
"onAddToFavorites",
"onPageScroll",
"onResize",
"onTabItemTap"
]
"onShow", "onReady", "onHide", "onUnload", "onPullDownRefresh", "onReachBottom",
"onShareAppMessage", "onShareTimeline","onAddToFavorites","onPageScroll", "onResize", "onTabItemTap"
];
/**
*
@ -288,9 +345,10 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
* @param depend
* @returns
*/
public addModule<DEP extends Depends<this>, M extends Modular<this, DEP>>
(mode: new (manager:Manager<WXC>, nameSpace:string, depend?:DEP) => M,
nameSpace:string, depend?:DEP):M {
public addModule<DEP extends Depends<this>, M extends Modular<this, DEP>> (
mode: new (manager:this, nameSpace:string, depend?:DEP) => M,
nameSpace:string, depend?:DEP
):M {
let mod = new mode(this, nameSpace, depend);
this.modules.push(mod);
return mod;
@ -300,14 +358,14 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
*
* @param key
*/
public creatHooks(key:keyof ILifetime):(...arg: any[]) => Promise<any> {
return async (...arg: any[]) => {
public creatHooks<Key extends keyof ILifetime>(key: Key): ILifetime[Key] {
let hook = (async (...arg: any[]) => {
let hooks:Promise<any>[] = [];
for(let i = 0; i < this.modules.length; i++) {
let fn:Function = (this.modules[i] as IAnyTypeObject)[key];
let fn:Function = this.modules[i][key];
if(fn === void 0) continue;
let res: Promise<any> | any = fn.apply(this.modules[i], arg);
@ -340,7 +398,10 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
}
return Promise.all(hooks);
}
});
// TODO: 此处为,关键位置,容易出错,请再次检查
return (hook as any);
}
/**
@ -383,7 +444,7 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
this.context.setData(this.context.data);
// 调用全部模块的 onLoad 周期
let res = this.creatHooks("onLoad")(query as any);
let res = this.creatHooks("onLoad")(query);
// 打印每个模块的键值对使用情况
for(let i = 0; i < this.modules.length; i++) {
@ -411,9 +472,9 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
/**
*
*/
public static readonly AddModuleLabel = new LogLabel("addModule",
new LogStyle().setBorder("4px", `1px solid #8600FF`)
.setColor("#FF00FF", "rgba(54, 0, 255, .2)").setBlank("0 5px")
public static readonly AddModuleLabel = new LogLabel(
"addModule",
colorRadio(54, 0, 255)
)
/**

View File

@ -1,5 +1,13 @@
import { Logger, LogLabel, LevelLogLabel, colorRadio } from "./Logger";
interface IAppStorageParam {
/**
* storage
*/
storage: Map<string, Storage<IStorageData>>
}
/**
*
*/
@ -81,7 +89,8 @@ type IStorageData = {
* 1. wxStorage
* 2.
* 3. 使
* 4.
* 4. storage
*
*/
class Storage<T extends IStorageData> {
@ -103,18 +112,41 @@ class Storage<T extends IStorageData> {
/**
*
*/
private cache:T;
private _cache: T = {} as T;
private set cache(data: T) {
if (this.cacheStorage) {
for (const key in data) {
this.cacheStorage.cache[key] = data[key];
}
} else {
for (const key in data) {
this._cache[key] = data[key];
}
}
}
private get cache():T {
if (this.cacheStorage) return this.cacheStorage.cache;
else return this._cache;
}
/**
* cache storage
*/
private saveWaiter:Waiter = new Waiter();
/**
*
*/
private cacheStorage:Storage<T> | undefined;
/**
* cache storage
*/
public async save():Promise<void> {
// 如果存在链接的实例
if (this.cacheStorage) return this.cacheStorage.save();
// 如果没有开始存储
// 发起一次异步读取
if(this.saveWaiter.state === StorageState.DONE)
@ -150,6 +182,24 @@ class Storage<T extends IStorageData> {
});
}
/**
*
*/
private findStorageCache(): boolean {
let { storage: storageMap } = getApp<IAppStorageParam>();
// 查找缓存
let storage = storageMap.get(this.key);
if (storage) {
this.cacheStorage = storage as Storage<T>;
return true;
};
// 缓存此实例
storageMap.set(this.key, this);
return false;
}
/**
*
*/
@ -164,13 +214,25 @@ class Storage<T extends IStorageData> {
/**
* @param defaultData
*/
public constructor(key:string, defaultData:T) {
public constructor(key:string, defaultData?:T) {
this.key = key;
this.defaultData = defaultData;
this.defaultData = defaultData ?? {} as T;
this.StorageLogLabel = new LogLabel(
`Storage:${ this.key }`, colorRadio(34, 230, 258)
);
// 如果已找到其他实力,将此实例链接到目标实例
if (this.findStorageCache()) {
// 设置默认值
for (const key in this.defaultData) {
if (this.cache[key] === void 0) {
this.set(key, this.defaultData[key]);
}
}
return;
};
// 读取数据到缓存
this.cache = wx.getStorageSync<T>(this.key);
@ -205,4 +267,4 @@ class Storage<T extends IStorageData> {
}
export default Storage;
export { Storage, StorageState, Waiter };
export { Storage, StorageState, Waiter, IAppStorageParam, IStorageData };

View File

@ -1,205 +0,0 @@
// import { Logger } from "../logger/Logger";
import { LogStyle, LogLabel } from "./Logger";
/**
*
*/
class TestResult {
/**
*
*/
public caseName:string;
/**
*
*/
public result:boolean;
/**
*
*/
public message:string;
/**
*
*/
public attach:string;
/**
*
* @param caseName
*/
constructor(caseName:string) {
this.caseName = caseName;
this.result = false;
this.message = "";
this.attach = "";
}
/**
*
*/
public setResult(result:boolean, message?:string, attach?:string) {
this.result = result;
this.message = message ?? (result ? "success!" : "failed!");
this.attach = attach ?? this.attach;
return this;
}
}
/**
*
*/
type TestFunction = () => TestResult | Promise<TestResult>;
/**
*
*/
class CaseCollect {
/**
*
*/
public key:string;
/**
*
*/
public caseFunction:TestFunction;
/**
*
*/
result: Promise<TestResult> | undefined;
/**
* @param key
* @param caseFunction
*/
public constructor(key:string, caseFunction:TestFunction) {
this.key = key;
this.caseFunction = caseFunction;
}
/**
*
*/
public async runTestCase():Promise<CaseCollect> {
let result = this.caseFunction();
if(result instanceof Promise) {
this.result = result;
} else {
this.result = Promise.resolve(result);
}
return this;
}
public static readonly baseStyle = new LogStyle().setBlank();
public static readonly successLabel:LogLabel = new LogLabel("√",
new LogStyle().setBlank("0 4px").setBorder("1000px", "1px solid green")
);
/**
*
* @param current
* @param total
*/
public printResult(current?:number, total?:number) {
// 如果测试没有运行,先运行它
if(this.result === void 0) this.runTestCase();
this.result?.then((res) => {
if(res.result) {
console.log(
`%c√%c %c1/1%c %c${ this.key }%c ` + res.message,
"padding:0 4px; border-radius:1000px; border:1px solid green; color:green",
"", "padding:0 4px; border-radius:4px; border:1px solid green; color:green",
"", "padding:0 4px; border-radius:4px; border:1px solid #979797; color:#979797",
""
)
} else {
console.log(
`%c√%c %c1/1%c %c${ this.key }%c ` + res.message,
"padding:0 4px; border-radius:1000px; border:1px solid red; color:red",
"", "padding:0 4px; border-radius:4px; border:1px solid red; color:red",
"", "padding:0 4px; border-radius:4px; border:1px solid #979797; color:#979797",
""
)
}
console.log(res)
})
}
/**
*
* @param testCaseClass
*/
public static collectCase(testCaseClass:ITestCase):CaseCollect[] {
// 获取静态方法 key
let key = Object.getOwnPropertyNames(testCaseClass);
// 过滤掉通用的方法和属性
key = key.filter((key) => !/(length|name|prototype)/.test(key) );
// 生成 CaseCollect
let caseCollect = [];
for (let i = 0; i < key.length; i++) {
caseCollect.push(new CaseCollect(key[i], testCaseClass[key[i]]))
}
return caseCollect;
}
/**
*
*/
public static async runCollectCase(cases:CaseCollect[]):Promise<CaseCollect[]> {
let running:Promise<CaseCollect>[] = [];
for(let i = 0; i < cases.length; i++) {
running.push(cases[i].runTestCase());
}
return Promise.all(running);
}
/**
*
*/
public static runUnitTest(testCaseClass:ITestCase) {
let caseCollect = this.collectCase(testCaseClass);
CaseCollect.runCollectCase(caseCollect).then((caseCollect:CaseCollect[]) => {
for(let i = 0; i < caseCollect.length; i++) {
caseCollect[i].printResult()
}
})
}
}
/**
*
*/
interface ITestCase {
/**
*
*/
[key:string]:TestFunction;
}
export default ITestCase;
export { ITestCase, TestResult, TestFunction, CaseCollect };

View File

@ -4,7 +4,7 @@ import { Logger, LogLabel, LevelLogLabel, LifeCycleLogLabel, NormalStyle } from
/**
* UI
*/
type DisplayData = {
interface IDisplayData {
/**
*
@ -20,8 +20,8 @@ type DisplayData = {
/**
*
*/
type StatusBarEvent = {
m: DisplayData
interface StatusBarEvent {
m: IDisplayData
};
/**

View File

@ -8,13 +8,22 @@ import { Storage } from "../../core/Storage";
class TestCore<M extends Manager> extends Modular<M>
implements Partial<ILifetime> {
public onLoad() {
public override onLoad() {
let s = new Storage("test", {
a: new Date(),
be: 2
});
let s2 = new Storage("test", {
be: 1,
aa: "abc"
});
s2.set("be", 4);
console.log(s, s2);
setTimeout(() => {
s.set("be", 12);
}, 1000)
@ -55,9 +64,7 @@ implements Partial<ILifetime> {
}
}).request().wait({
success: (d) => console.log(d)
}).wait({
success: (d) => console.log(d)
});
})
}
}