首页 > 解决方案 > 在任何页面上仅从服务加载一件事

问题描述

我有一个电话/accounts,我只想在用户登陆的任何页面上立即发生一次。一旦调用,它要么将用户踢回主页,要么将该信息添加到商店。如果它在商店里,我不希望它再次被调用。

目前我正在尝试使用以下方法做这样的事情take(1)

@Effect()
loadAccounts$: Observable<Action> = this.actions$.pipe(
    ofType(actions.ActionTypes.LoadAccounts),
    switchMap((action: actions.LoadAccounts) => {
        return this.accountService.getAccounts().pipe(
            map(accts => new actions.LoadAccountsSuccess(accts)),
            catchError(error => {
                this.store.dispatch(new LoadAccountsFailure(error));
                return EMPTY;
            }),
        );
    }),
    take(1),
);

我看到的一个问题是:

export const selectWorkspacesLoadInProgress = AppSelectors.selectChangesIndicatorInProgress([
    AccountActions.ActionTypes.LoadAccounts,
    ConfigActions.ActionTypes.LoadProjects,
    WorkspaceListActions.ActionTypes.LoadWorkspaces,
]);

在我们将帐户信息加载到商店后,我看到 loadInProgress 卡在之后对 loadAccounts 的任何调用上。加载帐户的动作 has@ShowInProgressIndicator(ActionTypes.LoadAccounts)和 load account success/failure then have @HideIndicator(ActionTypes.LoadAccounts)... 但是使用take(1),似乎我们仍然触发了showhides 永远不会被触发。

我也有点不确定我应该如何从多个页面处理这个......现在,在我正在使用的任何页面的主页组件上ngOnInit

    this.store.dispatch(new AccountActions.LoadAccounts());

我有一个组件需要在帐户调用成功后进行额外调用。我这样做的效果是:

@Effect()
addServiceToWorkspace$: Observable<Action> = this.actions$.pipe(
    ofType(actions.ActionTypes.AddService),
    mergeMap((action: actions.AddService) =>
        this.serviceService.add(action.request).pipe(
            mergeMap(() => [new actions.AddServiceSuccess(action.request.workspaceId), new actions.StopAddingService()]),
            catchError((error) => of(new actions.AddServiceFailure(errorToErrorMessage(error)))),
        ),
    ),
);

但我注意到这会在我所在的任何页面上被调用,而且我不确定如何限制它......除了可能loadAccounts为每个页面创建几乎重复的动作/效果。


试图总结...

什么是完成每个会话为商店中的项目进行 1 次服务调用的好方法,无论它们落在哪个组件上......并且让这些组件依赖(等待)这些数据存在(来自的调用获取数据的服务,或使用存储中的数据)......而不会弄乱依赖于successfailure已达到的操作的事情?

标签: rxjsngrxngrx-effects

解决方案


一种选择是将一个添加if到您的选择器管道。像这样的东西:

this.products$ = this.store.select(getProducts).pipe(
  tap(x => {
    if (x.length === 0) {
      this.store.dispatch(ProductActions.loadProducts());
    }
  })
);

不过,不确定这种技术是否是“最佳实践”。


推荐阅读