使用带有apollo-client的RxJs takeUntil()函数

时间:2017-07-17 17:45:27

标签: reactjs react-apollo redux-observable apollo-client

我正在使用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()。

谢谢

1 个答案:

答案 0 :(得分:1)

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

redux-observable只有99.9%只是RxJS,所以所有运算符都不知道redux / actions 之外的ofType这是唯一的运算符redux-observable提供的 - 其余的是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'))
    );
};

然而,使用Promise thencatch这样的说法可能不合适 - 如果您更喜欢使用Promises,我可能会建议不要使用redux-observable。当使用redux-observable时,如果我们没有其他选择(例如我们不控制apollo-client API),我们通常只能使用Promises。在这些情况下,我通常尽可能快地将它们包装为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 catch还是Observable catch?”。当然,这只是我的观点:))

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