mobx-loading
mobx-loading copied to clipboard
部署以后 key 会改变,导致取不到
可以提供一个在线的可复现的完整代码示例吗?
@clock157 怎么操作导致 key 发生的改变,或者能详细描述一下吗?
因为 models 名取自 target.constructor.name
. JS 一压缩就没了.
因为 models 名取自
target.constructor.name
. JS 一压缩就没了.
正解!
@niqingyang 我把你的代码复制到本地加以改造以实现更丰富的功能, 其中包含很多野路子. 目前有点忙没时间提交 patch, 因为暂时自己也理不清如何把这种设计思路解耦出来单独使用.
这里我提供一下我的思路:
前提是我采用了官方文档里联合多个 store 的建议 https://mobx.js.org/best/store.html#combining-multiple-stores
首先我把 loadingStore.actions
的类型从 { 'aStore/anAction': false }
改造成了 { aStore: { aAction: false } }
之后在 @loading
装饰器执行时不去猜测名称, 为了省事我也禁止了自定义名称. 而是把 target
对象直接向下传入 executeAction
函数.
在 executeAction
函数的返回值里, 我会把 target
进一步传入 loadingStore.change
.
同时我会直接通过
target
找到当前 Store name 和 action name 对loadingStore.actions
和loadingStore.models
进行初始化工作, 将默认值设为false
, 这一步的工作可以避免loading
值为undefined
的情况.
最后在 loadingStore.change
里面我用 target
对象, 顺着 this.rootStore
找到 model name.
Object.keys(this.rootStore).find(
key => this.rootStore[key] instanceof target.constructor
);
还没结束, 我们用 Mobx 的人怎么可能忍受像 Redux 一样处处是 any 的日子.
我的类定义是这样的
class LoadingStore<R = any>
我的 models 定义是这样的
models = {} as { [M in keyof R]?: boolean };
我的 actions 定义是这样的
actions = {} as {
[M in keyof R]?: PickAsyncFunctionAsBoolean<Partial<R[M]>>
};
我的 RootStore 定义是这样的
export class RootStore {
loadingStore: LoadingStore<RootStore>;
}
PickAsyncFunctionAsBoolean
的类型定义是这样的, 这里我只能拿到所有 async 属性, 无法判断是不是带 @loading
装饰器, 以目前的 typescript 去做这件事, 还没有靠谱的解决方案, 网上倒是真的有个疯子研究过这件事情.
type AsyncFunction = (...args: any[]) => Promise<any>;
type AsyncFunctionAsBoolean<T> = { [P in keyof T]: T[P] extends AsyncFunction ? boolean : never };
type OmitNeverValue<T> = Pick<T, { [P in keyof T]: T[P] extends never ? never : P }[keyof T]>;
/** Pick all async function field and set type to boolean. */
type PickAsyncFunctionAsBoolean<T> = OmitNeverValue<AsyncFunctionAsBoolean<T>>;
最终效果就是 loadingStore.actions.userStore?.loadProfile
是有类型提示的
executeAction
函数有个需要改进的地方就是返回 async function. 这样可以解决问题 https://github.com/niqingyang/mobx-loading/issues/3
// 以这种方式返回, 才可以被 try catch
return async function() {
try {
loadingStore.change(target, propertyKey, true);
return await func.apply(scope || this, arguments);
} catch (err) {
throw err;
} finally {
loadingStore.change(target, propertyKey, false);
}
};
@niqingyang 我把你的代码复制到本地加以改造以实现更丰富的功能, 其中包含很多野路子. 目前有点忙没时间提交 patch, 因为暂时自己也理不清如何把这种设计思路解耦出来单独使用.
这里我提供一下我的思路:
前提是我采用了官方文档里联合多个 store 的建议 https://mobx.js.org/best/store.html#combining-multiple-stores
首先我把
loadingStore.actions
的类型从{ 'aStore/anAction': false }
改造成了{ aStore: { aAction: false } }
之后在
@loading
装饰器执行时不去猜测名称, 为了省事我也禁止了自定义名称. 而是把target
对象直接向下传入executeAction
函数.在
executeAction
函数的返回值里, 我会把target
进一步传入loadingStore.change
.同时我会直接通过
target
找到当前 Store name 和 action name 对loadingStore.actions
和loadingStore.models
进行初始化工作, 将默认值设为false
, 这一步的工作可以避免loading
值为undefined
的情况.最后在
loadingStore.change
里面我用target
对象, 顺着this.rootStore
找到 model name.Object.keys(this.rootStore).find( key => this.rootStore[key] instanceof target.constructor );
还没结束, 我们用 Mobx 的人怎么可能忍受像 Redux 一样处处是 any 的日子.
我的类定义是这样的
class LoadingStore<R = any>
我的 models 定义是这样的
models = {} as { [M in keyof R]?: boolean };
我的 actions 定义是这样的
actions = {} as { [M in keyof R]?: PickAsyncFunctionAsBoolean<Partial<R[M]>> };
我的 RootStore 定义是这样的
export class RootStore { loadingStore: LoadingStore<RootStore>; }
PickAsyncFunctionAsBoolean
的类型定义是这样的, 这里我只能拿到所有 async 属性, 无法判断是不是带@loading
装饰器, 以目前的 typescript 去做这件事, 还没有靠谱的解决方案, 网上倒是真的有个疯子研究过这件事情.type AsyncFunction = (...args: any[]) => Promise<any>; type AsyncFunctionAsBoolean<T> = { [P in keyof T]: T[P] extends AsyncFunction ? boolean : never }; type OmitNeverValue<T> = Pick<T, { [P in keyof T]: T[P] extends never ? never : P }[keyof T]>; /** Pick all async function field and set type to boolean. */ type PickAsyncFunctionAsBoolean<T> = OmitNeverValue<AsyncFunctionAsBoolean<T>>;
最终效果就是
loadingStore.actions.userStore?.loadProfile
是有类型提示的
executeAction
函数有个需要改进的地方就是返回 async function. 这样可以解决问题 #3// 以这种方式返回, 才可以被 try catch return async function() { try { loadingStore.change(target, propertyKey, true); return await func.apply(scope || this, arguments); } catch (err) { throw err; } finally { loadingStore.change(target, propertyKey, false); } };
😁 思路挺好的,我目前可能没太多时间去维护这个项目,欢迎你们任意改造 ~
@niqingyang 我把你的代码复制到本地加以改造以实现更丰富的功能, 其中包含很多野路子. 目前有点忙没时间提交 patch, 因为暂时自己也理不清如何把这种设计思路解耦出来单独使用.
这里我提供一下我的思路:
前提是我采用了官方文档里联合多个 store 的建议 https://mobx.js.org/best/store.html#combining-multiple-stores
首先我把
loadingStore.actions
的类型从{ 'aStore/anAction': false }
改造成了{ aStore: { aAction: false } }
之后在
@loading
装饰器执行时不去猜测名称, 为了省事我也禁止了自定义名称. 而是把target
对象直接向下传入executeAction
函数.在
executeAction
函数的返回值里, 我会把target
进一步传入loadingStore.change
.同时我会直接通过
target
找到当前 Store name 和 action name 对loadingStore.actions
和loadingStore.models
进行初始化工作, 将默认值设为false
, 这一步的工作可以避免loading
值为undefined
的情况.最后在
loadingStore.change
里面我用target
对象, 顺着this.rootStore
找到 model name.Object.keys(this.rootStore).find( key => this.rootStore[key] instanceof target.constructor );
还没结束, 我们用 Mobx 的人怎么可能忍受像 Redux 一样处处是 any 的日子.
我的类定义是这样的
class LoadingStore<R = any>
我的 models 定义是这样的
models = {} as { [M in keyof R]?: boolean };
我的 actions 定义是这样的
actions = {} as { [M in keyof R]?: PickAsyncFunctionAsBoolean<Partial<R[M]>> };
我的 RootStore 定义是这样的
export class RootStore { loadingStore: LoadingStore<RootStore>; }
PickAsyncFunctionAsBoolean
的类型定义是这样的, 这里我只能拿到所有 async 属性, 无法判断是不是带@loading
装饰器, 以目前的 typescript 去做这件事, 还没有靠谱的解决方案, 网上倒是真的有个疯子研究过这件事情.type AsyncFunction = (...args: any[]) => Promise<any>; type AsyncFunctionAsBoolean<T> = { [P in keyof T]: T[P] extends AsyncFunction ? boolean : never }; type OmitNeverValue<T> = Pick<T, { [P in keyof T]: T[P] extends never ? never : P }[keyof T]>; /** Pick all async function field and set type to boolean. */ type PickAsyncFunctionAsBoolean<T> = OmitNeverValue<AsyncFunctionAsBoolean<T>>;
最终效果就是
loadingStore.actions.userStore?.loadProfile
是有类型提示的
executeAction
函数有个需要改进的地方就是返回 async function. 这样可以解决问题 #3// 以这种方式返回, 才可以被 try catch return async function() { try { loadingStore.change(target, propertyKey, true); return await func.apply(scope || this, arguments); } catch (err) { throw err; } finally { loadingStore.change(target, propertyKey, false); } };
@niqingyang 我把你的代码复制到本地加以改造以实现更丰富的功能, 其中包含很多野路子. 目前有点忙没时间提交 patch, 因为暂时自己也理不清如何把这种设计思路解耦出来单独使用.
这里我提供一下我的思路:
前提是我采用了官方文档里联合多个 store 的建议 https://mobx.js.org/best/store.html#combining-multiple-stores
首先我把
loadingStore.actions
的类型从{ 'aStore/anAction': false }
改造成了{ aStore: { aAction: false } }
之后在
@loading
装饰器执行时不去猜测名称, 为了省事我也禁止了自定义名称. 而是把target
对象直接向下传入executeAction
函数.在
executeAction
函数的返回值里, 我会把target
进一步传入loadingStore.change
.同时我会直接通过
target
找到当前 Store name 和 action name 对loadingStore.actions
和loadingStore.models
进行初始化工作, 将默认值设为false
, 这一步的工作可以避免loading
值为undefined
的情况.最后在
loadingStore.change
里面我用target
对象, 顺着this.rootStore
找到 model name.Object.keys(this.rootStore).find( key => this.rootStore[key] instanceof target.constructor );
还没结束, 我们用 Mobx 的人怎么可能忍受像 Redux 一样处处是 any 的日子.
我的类定义是这样的
class LoadingStore<R = any>
我的 models 定义是这样的
models = {} as { [M in keyof R]?: boolean };
我的 actions 定义是这样的
actions = {} as { [M in keyof R]?: PickAsyncFunctionAsBoolean<Partial<R[M]>> };
我的 RootStore 定义是这样的
export class RootStore { loadingStore: LoadingStore<RootStore>; }
PickAsyncFunctionAsBoolean
的类型定义是这样的, 这里我只能拿到所有 async 属性, 无法判断是不是带@loading
装饰器, 以目前的 typescript 去做这件事, 还没有靠谱的解决方案, 网上倒是真的有个疯子研究过这件事情.type AsyncFunction = (...args: any[]) => Promise<any>; type AsyncFunctionAsBoolean<T> = { [P in keyof T]: T[P] extends AsyncFunction ? boolean : never }; type OmitNeverValue<T> = Pick<T, { [P in keyof T]: T[P] extends never ? never : P }[keyof T]>; /** Pick all async function field and set type to boolean. */ type PickAsyncFunctionAsBoolean<T> = OmitNeverValue<AsyncFunctionAsBoolean<T>>;
最终效果就是
loadingStore.actions.userStore?.loadProfile
是有类型提示的
executeAction
函数有个需要改进的地方就是返回 async function. 这样可以解决问题 #3// 以这种方式返回, 才可以被 try catch return async function() { try { loadingStore.change(target, propertyKey, true); return await func.apply(scope || this, arguments); } catch (err) { throw err; } finally { loadingStore.change(target, propertyKey, false); } };
https://github.com/webclipper/web-clipper/blob/master/src/common/loading.ts
我也自己实现了一份。API 略有不同。
因为 models 名取自
target.constructor.name
. JS 一压缩就没了.正解!
这里有啥好的解决办法吗