Redux 可观察超时重试

Redux observable retry on timeout

我想使用 redux-observable 处理 ajax 超时,这样如果发生超时(比如 10 秒后),它将再重试请求两次(触发 SAVE_RETRYING 操作,这样 UI 可以通知用户它正在重试)。

对于任何其他类型的错误,或者如果我们已经重试了两次,它应该会失败并触发 SAVE_FAILURE 操作。

如果我使用 store.dispatch 触发 SAVE_RETRYING 操作,我可以让它工作,但收到关于此的弃用警告,我有点不知道如何以正确的方式做到这一点(添加SAVE_RETRYING 到史诗返回的流)。

这是我的(简体):

function saveEpic(action$, store) {
  return action$.ofType('SAVE_CLICKED')
    .mergeMap(action => (
      ajax({
        url: '/a-long-request',
      })
        .timeout(10000)
        .map(() => ({ type: 'SAVE_SUCCESS' }))
        .retryWhen(errors => (
          errors.scan((count, e) => {
            if (count >= 2 || e.name !== 'TimeoutError') {
              throw e;
            } else {
              store.dispatch({ type: 'SAVE_RETRYING', count });
              return count + 1;
            }
          }, 0)))
        .startWith({ type: 'SAVE_STARTED' })
        .catch(() =>
          Observable.of({ type: 'SAVE_FAILURE' }))
    ));
}

如何才能将 SAVE_RETRYING 操作添加到主流?谢谢

这并不理想,但您可以使用 catch 和未记录的第二个参数(可观察到的源)重新订阅。我不喜欢的缺点是你必须在 mergeMap 回调闭包中计算重试次数。

function saveEpic(action$, store) {
  return action$.ofType('SAVE_CLICKED')
    .mergeMap(action => {
      let retries = 0;
      return ajax({
        url: '/a-long-request',
      })
        .timeout(10000)
        .map(() => ({ type: 'SAVE_SUCCESS' }))
        .catch((error, source) => {
          retries += 1;
          if (retries >= 2 || error.name !== 'TimeoutError') {
            return Observable.of({ type: 'SAVE_FAILURE' });
          }

          return source.startWith({ type: 'SAVE_RETRYING', count: retries });
        })
        .startWith({ type: 'SAVE_STARTED' });
    });
}