首页 > 解决方案 > 从 API 加载数据后从商店加载特定数据

问题描述

我在我的项目中具有这种RXJS效果,在该操作中,我正在从服务器加载一个组织,然后尝试从NGRX基于organisation ID. 在效果结束时,我用数据发送我的成功操作。


selectOrganisation$ = createEffect(() => this.actions$.pipe(
    ofType(OrganisationsActionTypes.SelectOrganisation),
    withLatestFrom(
      this.store.pipe(select(AuthSelectors.selectCurrentUser)),
      this.store.pipe(select(ContextSelectors.getContext))
    ),
    switchMap(([action, user, context]) =>
      forkJoin([
        of(user),
        of(context),
        this.organisationService.getOrganisationById(context, action.id),
        this.moduleService.getAllSimpleModules(context)
      ])
    ),
    switchMap(([user, context, organisation, modules]) =>
      forkJoin([
        of(organisation),
        of(modules),
        this.store.pipe(select(BookmarkSelectors.selectBookmarkByOrganisation, {
          userId: user.id,
          context,
          organisationKey: organisation.key
        }))
      ])
    ),
    switchMap(([organisation, modules, bookmark]) => [
      onSelectOrganisation({organisation, modules, bookmark})
    ]),
    catchError(error => of(onSelectOrganisationError()))
  ));

问题是我的成功动作永远不会触发,我也不会error被抛出。我可以对所有的效果进行断点,switchMaps并查看除最后一个之外的数据,它永远不会被击中,所以我怀疑我的书签选择器可能有问题。

我的书签选择器看起来像这样,此时数组中没有书签,所以这个函数返回undefined.

export const selectBookmarkByOrganisation = createSelector(
  selectAllBookmarks,
  (bookmarks: BookmarkDto[], props) => {
    const bookmark = _.chain(bookmarks)
      .filter(b =>
        b.userId === props.userId
        && b.serverContext === props.context
        && b.organisationKey === props.organisationKey)
      .first()
      .value();
    return bookmark;
  }
);

对我来说,这似乎有点混乱,我正在寻找一些关于如何改进此代码并同时消除此错误的指示!

标签: angularrxjsngrx-effects

解决方案


似乎最后forkJoin没有发出任何东西(根据定义)

如果内部 observable 没有完成,forkJoin 将永远不会发出值!

遵循您的选择器应该complete

我建议take(1)/first在选择器上使用来完成它(另外,尝试使用startWith(但我认为undefined应该没问题))。

此外,“动作”switchMap转移到map- 无需“扁平化”

应该像这样工作:

switchMap(([user, context, organisation, modules]) =>
  forkJoin([
    of(organisation),
    of(modules),
    this.store.pipe(
      select(BookmarkSelectors.selectBookmarkByOrganisation, {
        userId: user.id,
        context,
        organisationKey: organisation.key
      }),
      take(1),
    )
  ])
),
map(([organisation, modules, bookmark]) =>
  onSelectOrganisation({organisation, modules, bookmark})
),

对于一般调整:简化一点(如果可能的话) - 到很多ofs,,switchMaps也许看看之间的区别zip/combineLatest/etc


推荐阅读