Akita中selectAll在服务调用完成前返回空列表问题咨询
为什么会先返回空列表
Akita的EntityStore初始化时,实体集合的默认初始值就是空数组。所有通过selectXXX方法创建的Observable,被订阅时会优先推送当前store的最新状态值,此时你的异步服务请求还未完成、store还未写入数据,所以第一次推送的就是初始空数组。等到服务请求返回、调用WidgetStore.add更新store后,才会推送第二次包含真实数据的结果。
如何过滤初始化的空数组
你可以通过给store新增自定义加载状态标记实现需求,步骤如下:
- 扩展
WidgetState,新增字段标记历史数据是否完成加载
// widget.state.ts import { EntityState } from '@datorama/akita'; export interface WidgetState extends EntityState<WidgetTO, number> { isHistorikkLoaded: boolean; }
- 初始化
WidgetStore时给状态字段设默认值false
// widget.store.ts @Injectable({ providedIn: 'root' }) export class WidgetStore extends EntityStore<WidgetState> { constructor() { super({ isHistorikkLoaded: false }); } }
- 数据请求成功后,同步更新加载状态为
true
private fetchWidgetHistorikk() { this.WidgetService.getWidgetHistorikk().pipe(filter(h => !!h)).subscribe(liste => { this.WidgetStore.add(liste); // 标记数据加载流程完成 this.WidgetStore.update({ isHistorikkLoaded: true }); }); }
- 修改Query中的查询流,组合加载状态过滤未初始化的空值
@Injectable({ providedIn: 'root' }) export class WidgetQuery extends QueryEntity<WidgetState, WidgetTO> { public Widget$: Observable<WidgetTO> = this.selectActive().pipe(filter(k => !!k)); public WidgetHistorikk$: Observable<WidgetTO[]> = combineLatest([ this.selectAll({sortBy: 'WidgetId', sortByOrder: Order.DESC}), this.select(state => state.isHistorikkLoaded) ]).pipe( // 仅在加载完成后向下游推送数据,空数组也会正常推送 filter(([_, isLoaded]) => isLoaded), map(([historikkList]) => historikkList) ); constructor(protected store: WidgetStore) { super(store); } }
注:不推荐使用
skip(1)实现该需求,若异步请求速度快于订阅时机,会误跳过真实有效数据。
内容的提问来源于stack exchange,提问作者vikingsteve
相关产品推荐
相关产品推荐

