在 catchError 中发出多个操作 - Redux Observable

Posted

技术标签:

【中文标题】在 catchError 中发出多个操作 - Redux Observable【英文标题】:Emit multiple actions within catchError - Redux Observable 【发布时间】:2021-10-29 10:30:17 【问题描述】:

我有使用 rxjs 史诗的身份验证功能:

export const authWithEmailPasswordEpic = action$ =>
action$.pipe(
    filter(authUser.match),
    switchMap((payload) =>
        defer(() =>
            from(firebaseEmailPasswordAuth(payload)).pipe(
                mergeMap(() => of(clearAlertState(), stopLoading())),
                catchError(err =>
                    of(clearState(), createAlert(
                        status: err.code,
                        alertType: RED_ALERT,
                        alertTitle: err.message
                    )),
                )
            )
        )
    )
);

如果用户凭据不正确,我将发送警报,但我也想在 5 秒左右后删除警报。因此,我相信我需要发出两个动作来实现这一点,第二个是:

of(toggleAlert()).pipe(delay(5000)))

我将如何实现这一目标,或者有更好的方法吗?

【问题讨论】:

【参考方案1】:

你在正确的轨道上......对于一个更简单的版本,我会使用concat,我认为它读起来更好:

export const authWithEmailPasswordEpic = (action$) =>
  action$.pipe(
    filter(authUser.match),
    switchMap(( payload ) =>
      from(firebaseEmailPasswordAuth(payload)).pipe(
        mergeMap(() => of(clearAlertState(), stopLoading())),
        catchError((err) =>
          concat(
            [
              clearState(),
              createAlert(
                status: err.code,
                alertType: RED_ALERT,
                alertTitle: err.message,
              ),
            ],
            timer(5000).pipe(
              mapTo(toggleAlert())
            )
          )
        )
      )
    )
  );

有了这个图案,你就可以让它变得更漂亮。想象一下,您想要发送toggleAlert,除非用户发送了Action.CloseAlert。然后你可以把 timer.pipe 换成:

timer(5000).pipe(
  mapTo(toggleAlert()),
  takeUntil(action$.pipe(
    filter((action) => action.type === Action.CloseAlert)
  ))
);

另一个注意事项 - 我认为这里不需要defer()。 switchMap 立即订阅函数的结果,所以它应该不重要。需要的话加回来

【讨论】:

【参考方案2】:

您可以在catchError 之后使用delay(5000),然后使用mergeWithof(toggleAlert()) 来实现,如下所示:

export const authWithEmailPasswordEpic = action$ =>
  action$.pipe(
    filter(authUser.match),
    switchMap(( payload ) =>
      defer(() =>
        from(firebaseEmailPasswordAuth(payload)).pipe(
          mergeMap(() => of(clearAlertState(), stopLoading())),
          catchError(err =>
            of(
              clearState(),
              createAlert(
                status: err.code,
                alertType: RED_ALERT,
                alertTitle: err.message
              )
            )
          ),
          mergeWith(of(toggleAlert()).pipe(delay(5000)))
        )
      )
    )
  );

【讨论】:

我认为这行不通。这会将任何操作(包括clearStatecreateAlert)延迟5000 毫秒,然后在它们发出之前将它们全部替换为toggleAlert 是的,你没事,我的错。谢谢你的评论。顺便说一句,我更新了我的答案。再次感谢。 :)

以上是关于在 catchError 中发出多个操作 - Redux Observable的主要内容,如果未能解决你的问题,请参考以下文章

使用 laravel 向 api 发出多个请求

如何使用 catchError() 并且仍然返回带有 rxJs 6.0 的类型化 Observable?

如何使用操作查询发出多个 Alamofire 请求

Future中 try-catch 和 catchError

RxJs。如果我有两个 observable,如何抛出错误并继续发出值?

NestJS:拦截地图和catchError