如何防止加载数据第二次在NgRx?



我有一个DOM块:

<div (click)="toggle(block)">
<div *ngIf="block.opened">
<div *ngFor="let item of block.items"></div>
</div>
</div>

通过单击I调度动作从服务器加载数据并在块中显示此数据:

toggle(block: RegistryGroup) {
this.store.dispatch(RegistryActions.ToggleRegistryBlockAction(block));
this.store.dispatch(RegistryActions.LoadRegistryLayersAction(this.block));
}

第一个事件ToggleRegistryBlockActionblock的属性更改为true/false。第二个LoadRegistryLayersAction通过block.id向服务器发出请求,并将数据返回到与block相同的状态到属性block.items = Server Response;

在效果方面,我听动作LoadRegistryLayersAction:

loadRegistriesLayers$: Observable<Action> = createEffect(() =>
this.actions$.pipe(
ofType(RegistryActions.LoadRegistryLayersAction),
filter(
(registryGroup) =>
registryGroup.items && !registryGroup.items.length
),
switchMap((registryGroup: RegistryGroup) =>
from(this.registry.getRegistryLayers(registryGroup.Id)).pipe(
map((layers: { [key: string]: RegistryLayerItemGeneric[] }) => {
return RegistryActions.SuccessLoadRegistryLayersAction({
payload: {
layers: this.registry.createLayersMapWithObjects(layers),
registryGroupId: registryGroup.Id,
},
});
}),
catchError((error: Error) => {
return of(RegistryActions.ErrorRegistryLayersAction(error));
})
)
)
)
);

Ifilter动作并检查数据是否已经存在。我检查block是否有registryGroup.items && !registryGroup.items.length

问题是有时执行后,这个效果服务器可以返回空的[]。所以下次,当用户请求它时,它会重复发送请求。

如何修复它,不触摸服务器,如果数据被加载?

有多种解决方案:

  • 保持一个状态属性,可以是loading,loaded,empty,…
  • 保存在状态中获取的id列表,并在发送请求之前检查此列表
  • 不检查registryGroup.items.length,并将数组初始化为null

试试ngrx-loading-state库:

https://github.com/amzhang/ngrx-loading-state

实时演示以避免多次发出API加载:

https://stackblitz.com/edit/angular-ivy-rocjzb?file=src%2Fapp%2Fapp.component.ts

你要的是使用NgRx存储作为缓存。所以我们需要在某个地方追踪最后一次成功加载的年龄或存在。上面的库根据maxAge参数来决定是否需要API调用。在效果中查找filterLoading()函数。这就是检查发生的地方。

这是无稽之谈,NgRx总是如此。但它提供了一致性和可遵循的模式。