如何在 NgRx 效果中短路第二个服务调用并等待第一个服务调用完成

问题描述

我有一个应用程序,它使用 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 (将#修改为@)