使用 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 }));
})
)
)
);
});
收到事件后读取存储,然后过滤掉存储中已有值的发射。
detail = createEffect(() => {
return this.actions.pipe(
ofType(ProductDetailPage.loaded),
concatLatestFrom(() => this.store.select(selectProducts)),
filter(([{ payload }, products]) => !!products[payload.sku]),
mergeMap(([{payload}]) => {
...
})
)
})
我有一个包含 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 }));
})
)
)
);
});
收到事件后读取存储,然后过滤掉存储中已有值的发射。
detail = createEffect(() => {
return this.actions.pipe(
ofType(ProductDetailPage.loaded),
concatLatestFrom(() => this.store.select(selectProducts)),
filter(([{ payload }, products]) => !!products[payload.sku]),
mergeMap(([{payload}]) => {
...
})
)
})