使用 redux-observable 和 rxjs 6 获取新的访问令牌并重试操作?

Get a new access token and retry action using redux-observable and rxjs 6?

我是 rxjsredux-observable 的新手,我面临以下问题:

epic 中,我请求了一些东西,但我收到了 401,因为我当前的 access_token 已过期。所以我需要换一个新的然后重试请求。 为此,我使用我存储的 refresh_token。我找到了一个似乎适用于 rxjs verion 5.x 的解决方案,我正在尝试使用版本 6 来实现它,但我可能遗漏了一些东西并且操作永远无法完成:

我提出请求,由于 401 而失败。然后,我设法请求了新的 access_token,我得到了新的 access_token 但仅此而已,流是听回忆源永远不会执行。

我试过调整这个: 这是用版本 5.x 的 rxjs

实现的

这是我正在写的史诗:

export const fetchItems= (action$: any) => action$.pipe(
  ofType(ActionTypes.REQUEST_ITEMS),
  switchMap((action: any) => {
    return request('get', '/items', '', true);
  }),
  map((response: any) => successResponse(response.data)),
  catchError((error: AxiosError, source: any) => {
    if (isError401(error) {
      return action$.pipe(
        ofType(ActionTypes.SUCCESS_REFRESH_TOKEN),
        takeUntil(action$.ofType(ActionTypes.FAILURE_REFRESH_TOKEN)),
        take(1),
        mergeMapTo(source),
        merge(
          of(requestRefreshToken())
        )
      );
    } else {
      return failureResponse(error);
    }
  })
);

我知道我有一些 any 不应该存在,而且我没有提供太多背景信息让你帮助我,但也许你可以给我一个线索关于在哪里寻找问题。

从我之前展示的 link 来看,我没有使用 Observable.defer() 部分,但我想这不是这里的问题。无论如何,我也不知道如何使用 rxjs 6 实现该部分。

在我的 redux 开发工具中,我看到了这个操作:

REQUEST_ITEMS
REQUEST_REFRESH_TOKEN (this is the request of a new access_token passing the current refresh_token)
SUCCESS_REFRESH_TOKEN (this means that I've got a new access_token stored)

在此之后,我期待 mergeMapTo(source) 会再次开火 REQUEST_ITEMS(并且有一个新的有效 access_token 动作可以完成,这次落入 successResponse(response.data)),但它永远不会被触发。

万一有人需要知道这个问题的答案,原来我用错了catchError。 如此处所述:

此外,我不得不用 rxjs 提供的 ajax 替换 axios(我用于 http 请求)。

工作代码是这样的:

export const fetchItems = (action$: any, store: any) => action$.pipe(
  ofType(ActionTypes.REQUEST_ITEMS),
  mergeMap((action: any) => {
    return defer(() => {
        const access_token = store.value.data.auth.access_token;
        const options = {
          headers: {
            Authorization: `Bearer ${access_token}`,
          },
          url: '/items',
        };
        return ajax(options);
      })
      .pipe(
        map((response: any) => successItems(response.response)),
        catchError((error: any, source: any) => {
          if (isError401(error)) {
            return action$.pipe(
              ofType(ActionTypes.SUCCESS_REFRESH_TOKEN),
              takeUntil(action$.ofType(ActionTypes.FAILURE_REFRESH_TOKEN)),
              take(1),
              mergeMapTo(source),
              merge(
                of(requestRefreshToken())
              ),
            );
          } else {
            return of(failureItems(error));
          }
        })
      );
  })
);