使用 NgRx 时如何避免不必要的 API 调用

How to avoid unnecessary API call when working with NgRx

我有一个包含 2 个菜单项的应用程序;球队,球员。每当我在它们之间切换时,即使我有数据存储,我也不得不进行不必要的 api 调用。

效果文件如下: //auth.effects.ts

loadTeams$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(AuthActions.loadTeams),
      switchMap((action) =>
        this.apiService.teams$.pipe(
          tap(() => console.log('get teams request')),
          map((teams: Team[]) => AuthActions.loadTeamsSuccess({ teams })),
          catchError((error) => {
            console.log('err', error);
            return of(AuthActions.loadFailure({ error }));
          })
        )
      )
    );
  });

下面是我进行 api 调用的组件

团队-list.component.ts

export class TeamsListComponent implements OnInit {
  loading$?: Observable<boolean>;
  error$?: Observable<string>;
  teams$?: Observable<Team[]>;
  retrySubject$ = new BehaviorSubject<boolean>(true);

  constructor(private store: Store<State>) {}

  ngOnInit(): void {
    this.store.dispatch(loadTeams());
    this.teams$ = this.store.select(getTeams);
    this.error$ = this.store.select(getError);
    this.loading$ = this.store.select(getLoading);
  }

  fetchRetry() {
    this.retrySubject$.next(false);
  }
}

ngOnInit 中的这一行导致不必要的 api 调用。 this.teams$ = this.store.select(getTeams);

如何防止它在初始化应用程序时调用一次 api?

loadTeams$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(AuthActions.loadTeams),
      // read the actions$ for an load success event
      withLatestFrom(this.actions$.pipe(ofType(AuthActions.loadTeamsSuccess)),
      // no success event? no teams loaded, so go on
      filter(([loadTeamsAction, loadTeamsSuccessAction]) => !loadTeamsSuccessAction),
      // remove unnecessary action
      map(([loadTeams,]) => loadTeams),
      switchMap((action) =>
        this.apiService.teams$.pipe(
          tap(() => console.log('get teams request')),
          map((teams: Team[]) => AuthActions.loadTeamsSuccess({ teams })),
          catchError((error) => {
            console.log('err', error);
            return of(AuthActions.loadFailure({ error }));
          })
        )
      )
    );
  });

收到事件后读取存储,然后过滤掉存储中已有值的发射。

更多信息:https://timdeschryver.dev/blog/start-using-ngrx-effects-for-this/#enhance-your-action-with-global-store-state

detail = createEffect(() => {
  return this.actions.pipe(
    ofType(ProductDetailPage.loaded),
    concatLatestFrom(() => this.store.select(selectProducts)),
    filter(([{ payload }, products]) => !!products[payload.sku]),
    mergeMap(([{payload}]) => {
      ...
    })
  )
})