NgXs @selector不支持异步函数?如何在NGXS中实现异步选择器
NGXS异步选择器解决方案
首先明确:NGXS 原生 @Selector() 装饰器的设计初衷是接收状态快照、同步返回派生状态,默认不会对异步返回值做自动解析,所以你定义的async选择器会直接将Promise实例推入流中,才会出现需要二次处理的情况。
你可以根据业务场景选择以下任意方案解决:
方案1:用RxJS高阶操作符打平流(无需修改现有Selector定义)
使用switchMap+from操作符直接将流中的Promise转为Observable并打平,不需要改动现有Selector的代码:
import { from } from 'rxjs'; import { switchMap } from 'rxjs/operators'; // 订阅前通过pipe处理流 this.state$.pipe( switchMap(promise => from(promise)) ).subscribe(state => { // 此处可直接拿到IMyState实例,无需额外处理Promise });
如果需要复用处理后的流,可以直接封装为组件的成员变量:
state$ = this.store.select(MyStore.mainState).pipe(switchMap(p => from(p)));
方案2:重构为同步Selector(符合NGXS最佳实践)
异步逻辑本身不适合放在Selector中,建议将异步查询逻辑迁移到Action处理函数中,将结果存入状态后再用同步Selector读取,完全符合NGXS单向数据流设计:
// 1. 定义加载Action export class LoadActiveState {} // 2. 在State类中添加Action处理逻辑 @Action(LoadActiveState) async loadActiveState(ctx: StateContext<IMyStore>) { const activeState = await this.getActiveState(ctx.getState()); ctx.patchState({ activeState }); } // 3. 改写为同步Selector @Selector() static mainState(store: IMyStore): IMyState { return store.activeState; }
改写后直接订阅@Select(MyStore.mainState) state$: Observable<IMyState>;即可直接拿到状态实例,无额外处理成本。
内容的提问来源于stack exchange,提问作者Jeanluca Scaljeri
相关产品推荐
相关产品推荐

