1

我正在使用 Apollo-Client 对我的 GraphQL 服务器进行查询和突变。由于 Apollo 有自己的错误处理,因此实现 takeUntil 函数来取消我的查询调用和我的突变要困难得多。

使用 Apollo,我的突变如下所示:

export const languageTimeZoneEpic = (action$) => {
  return action$.ofType(CHANGE_LANGUAGE)
    .mergeMap(action => client.mutate({
      mutation: languageMutation,
      variables: { id: action.id,  language: action.selected_language }
    }).then(result => changeLanguageFulfilled(result))
      .catch(error => changeLanguageError(error))
  );
};

我的突变没有问题,如果有错误,它会捕获它。这里的问题是,如果我takeUntil()像下面的示例一样添加函数,我的函数就不再起作用了。

export const languageTimeZoneEpic = (action$) => {
  return action$.ofType(CHANGE_LANGUAGE)
    .mergeMap(action => client.mutate({
      mutation: languageMutation,
      variables: { id: action.id,  language: action.selected_language }
    }).then(result => changeLanguageFulfilled(result))
      .catch(error => changeLanguageError(error))
  ).takeUntil("END_LANGUAGE");
};

我想知道是否有一种方法可以使用该takeUntil()功能,即使我使用具有自己的错误处理的客户端。

*如果我在突变完成之前调度另一个动作,这里的 takeUntil() 将被调用。

谢谢

4

1 回答 1

1

takeUntil不接受字符串作为其参数。相反,它期望它订阅一个 Observable,使用第一个 next'd 值作为信号。

redux-observable 99.9% 只是 RxJS,所以所有操作符对 redux/actions 一无所知,除了redux-observable提供ofType的唯一操作符——其余的是 RxJS 内置的。

还有一个隔离问题。如果您将takeUntil放在您的外部mergeMap,您将取消整个 Epic,而不仅仅是特定的 apollo-client 客户端。相反,我们需要将它放在mergeMap,并且由于我们正在处理 Promise,因此我们需要使用Observable.from它来包装它。

export const languageTimeZoneEpic = (action$) => {
  return action$.ofType(CHANGE_LANGUAGE)
    .mergeMap(action =>
      Observable.from(
        client.mutate({
          mutation: languageMutation,
          variables: { id: action.id,  language: action.selected_language }
        })
        .then(result => changeLanguageFulfilled(result))
        .catch(error => changeLanguageError(error))
      )
        .takeUntil(action$.ofType('END_LANGUAGE'))
    );
};

然而,使用 Promisethencatch类似这样的方式可以说是不合适的——如果你更喜欢使用 Promise,我可能会建议不要使用 redux-observable。当使用 redux-observable 时,我们通常只会在别无选择的情况下使用 Promises(例如,我们不控制 apollo-client API)。在这些情况下,我通常会尽快将它们包装为 Observable,然后其余的都是普通的 RxJS。

export const languageTimeZoneEpic = (action$) => {
  return action$.ofType(CHANGE_LANGUAGE)
    .mergeMap(action =>
      Observable.from(client.mutate({
        mutation: languageMutation,
        variables: { id: action.id,  language: action.selected_language }
      }))
        .map(result => changeLanguageFulfilled(result))
        .catch(error => Observable.of(
          changeLanguageError(error)
        ))
        .takeUntil(action$.ofType('END_LANGUAGE'))
    );
};

这有时意味着它更冗长,但主要是关于不使用 Promise catch,因为这会使您的代码在 redux-observable 中非常难以遵循。“这是 Promise 捕获还是 Observable 捕获?”。当然,这只是我的看法:)


我假设 apollo-client 无法实际取消突变,因为真正的 Promise 是不可取消的。从技术上讲,此代码将忽略 Promise 的结果,而不是真正取消它(不可能)。

于 2017-07-17T18:29:42.197 回答