问题描述
我有一个应用程序,它使用 NgRx 效果和服务通过 REST API 从服务器获取我称之为书签的数组。该组件将分派操作以获取书签数组,并从状态中监听状态和书签数组的变化。
ngOnInit(): void {
this.serviceStatus$ = this.store.select(selectBookmarksstatus);
this.bookmarks$ = this.store.select(selectBookmarks);
this.store.dispatch(BookmarksActions.GetBookmarks());
}
BookmarksReducer 将更新 GetBookmarks 的状态,并将书签添加到 GetBookmarksCompleted 的状态。下面的 GetBookmarks 操作将导致状态更改为加载,GetBookmarksCompleted 将更改状态为未加载并将书签数组添加到状态。
const bookmarksReducerFn = createReducer(
initialState,on(BookmarksActions.GetBookmarks,(state,action) => {
return updateServiceStatus(state,ServiceStatusTypes.loading);
}),on(BookmarksActions.GetBookmarksCompleted,action) => {
return addBookmarksToState(state,action.bookmarks);
})
);
书签效果将监听 GetBookmarks 操作并使用书签服务从服务器获取书签。
getBookmarks$ = createEffect(() => {
return this.actions$.pipe(
ofType(BookmarksActionTypes.GetBookmarks),withLatestFrom(this.store.select(selectBookmarks),(action: Action,bookmarks: Bookmark[]) => {
return bookmarks;
}
),mergeMap((bookmarks: Bookmark[]) => {
if (bookmarks != null) { return [BookmarksActions.GetBookmarksCompleted({bookmarks: bookmarks})]; }
return this.bookmarksService.getBookmarks()
.pipe(
map((x: Bookmark[]) => {
return BookmarksActions.GetBookmarksCompleted({bookmarks: x});
}),catchError((error) => {
return of(BookmarksActions.GetBookmarksError({error: error}));
})
);
})
);
});
上面的 BookmarksEffects 将使用 ofType 过滤 GetBookmarks 操作,并使用 withLatestFrom 从状态中获取最新的书签数组。在 mergeMap 中,它将检查当前处于状态的书签是否为空或未定义,如果不是,将通过使用书签数组调用 GetBookmarksCompleted 来完成效果。这样做是为了它不会从服务器获取书签,如果它们已经处于该状态。我还有一个 ReloadBookmarks(未显示),它将强制从服务器获取。 mergeMap 的最后一部分将调用 bookmarkService.getBookmarks() 以通过 REST API 从服务器获取书签。成功后,如果发生错误,它将调用 GetBookmarksCompleted 或 GetBookmarksError。
这一切都运行良好。问题是当调用 bookmarksService.getBookmarks() 需要很长时间时会发生什么。这整个过程从连接到 /bookmarks 路由的书签组件的 ngOnInit 开始。如果用户导航到 /bookmarks 路由,则将创建组件并启动该过程。如果用户导航到另一条路线,然后返回 /bookmarks,则该组件将被销毁并重新创建,并且该过程将再次开始。如果第一次调用 bookmarksService.getBookmarks() 到第二次调用 bookmarksService.getBookmarks() 时还没有完成,它将进行两次 HTTP 调用。
我非常想以某种方式检测到这一点,而不是拨打第二个电话并等待第一个电话完成。在另一个非 NgRx 应用程序中,该服务将跟踪状态并知道第一个调用仍在进行中,并且不允许发生第二个 HTTP 调用。我正在努力寻找一种方法来用 NgRx 完成同样的事情。
我以为我可以检查效果中的状态并做出必要的决定(可能使用 NoOp 操作),但第一次的状态与第二次的状态相同,所以我无法区分。当书签效果第一次拦截 GetBookmarks 操作时,状态类似于 { status: loading,bookmarks: null }。如果 BookmarksEffects 拦截了对 GetBookmarks 的第二次调用,则在第一个 ahs 完成之前,状态是相同的。
我现在唯一的想法是向状态添加一个整数计数,并跟踪在 GetBookmarksCompeted 之前调用 GetBookmarks 的次数。每次调用 GetBookmarks 时,整数都可以增加 1。 bookmarksService.getBookmarks() 被调用的唯一时间是计数为 1 时。所有其他时间都可以使用 NoOp 操作。当调用 GetBookmarksCompleted 或 GetBookmarksError 时,计数将重置为 1。
我会对与拥有更多 NgRx 经验的其他人不同的观点很感兴趣。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)