这个 redux observable Epic 是如何工作的?

问题描述 投票:0回答:1

现在我正在处理网站身份验证,并且我已经添加了访问和刷新令牌。我想创建一个自动刷新操作来获取新的访问令牌。因此,如果我的服务器返回“访问被拒绝”错误,我想执行刷新并使用 RxJS 和 Redux Observable 重试之前的操作。

当我收到此错误时,我成功发出刷新请求(我正在遵循这些指南#1#2)。 但是,我仍然不知道如何再次调用主操作。 我希望操作按照主操作、刷新、主操作(再次)的顺序执行,但目前只有两个正在执行三个动作。

这是我的代码,因此在catchError中调用handleError函数来请求新的访问令牌(如果需要)

const handleError = (action$: Observable<any>, err: any, caught: Observable<any>) => {
    if (err.response?.errors?.[0]?.extensions?.code === "ACCESS_DENIED") {
        return action$.pipe(
            ofType(refreshSuccessActionCreator),
            takeUntil(action$.pipe(ofType(LOGOUT_ACTION))),
            take(1),
            mergeMap(() => caught), //it is supposed to try main action again, but it don't
            mergeWith(of(refreshActionCreator())), //calling refresh
        );
    }
    else {
        return of(workSessionErrorActionCreator(err));
    }
};

//my epic
export const GetActiveWorkSessionEpic: Epic = (action$: Observable<PayloadAction<string>>) =>
    action$.pipe(
        ofType(GET_ACTIVE_WORK_SESSION_ACTION),
        map(action => action.payload),
        mergeMap((userId) => RequestGetActiveWorkSession(userId).pipe(
            map(res => res.data?.workSession.getActiveWorkSessionByUserId),
            map(workSession => SetActiveWorkSession(workSession)),
            catchError((err, caught) => handleError(action$, err, caught)),
        ))
    );

//action creators
export const refreshActionCreator = () => ({type: REFRESH_ACTION});
export const refreshSuccessActionCreator = () => ({type: REFRESH_SUCCESS_ACTION});

//refresh epic
export const RefreshEpic: Epic = (action$) =>
    action$.pipe(
        ofType(REFRESH_ACTION),
        mergeMap(() => RequestRefresh().pipe(
            map(res => {
                if (res.data.auth.refresh) {
                    SetAccessToken(res.data.auth.refresh);
                }
                return refreshSuccessActionCreator();
            }),
            catchError(() => of(logoutActionCreator()))
        ))
    );

另外,我不明白我的handleError史诗是如何工作的:

  1. 为什么我必须传递actionCreator而不是
    ofType()
    中的动作类型?当我将操作类型放在这里时,它不起作用并无限地请求主要操作。
  2. 为什么
    mergeMap()
    在这里没有效果?”

我试图将

mergeMap
mergeWith
更改为
concatMap
concatWith
。还在这里尝试了更多 rxjs 运算符,但它不起作用。尝试更改
pipe()
中的位置。我不能太多,因为我不明白这部史诗,但我已经花了很多时间在它上面。

authentication rxjs refresh-token redux-observable epic
1个回答
0
投票
  1. 为什么我必须在 ofType() 中传递 actionCreator 而不是动作类型?当我将操作类型放在这里时,它不起作用并无限地请求主要操作。

看起来主要问题隐藏在可观察的源中。

ofType
应该按您的预期工作。但可观察的源可能只会重复第一次失败,这将导致无限循环。要解决这个问题,请参阅第二个问题的答案。

  1. 为什么mergeMap()在这里没有效果?

mergeMap((userId) => RequestGetActiveWorkSession(userId).pipe(
行可能有问题。源可观察的
RequestGetActiveWorkSession(userId)
显然不支持错误完成的重新订阅。

请将可观察源封装到

Observable.defer
,如参考指南中提到的那样。

引用指南 #1:

return Observable.defer(() => {
  // we have to use defer to create a block that only gets executed when source get resubscribed to it.
  return Observable.ajax(getData(data.id)) // api call to fetch data
})
© www.soinside.com 2019 - 2024. All rights reserved.