redux-observable和rxjs。将承诺转换为Observable - 史诗只被调用一次

时间:2018-01-11 14:14:18

标签: javascript promise rxjs rxjs5 redux-observable

我正在使用redux-observable来处理一个动作:

export const createPaymentMethod =
  (getBraintreeToken: (Object) => Promise<*>, cardholderName: string) => ({
    type: CREATE_PAYMENT_METHOD,
    getBraintreeToken: () => getBraintreeToken({ cardholderName }),
  });

const mapBraintreeError = err => Observable.of({
  type: CREATE_PAYMENT_METHOD + FAILURE,
  error: { response: err.message },
});

export const createPaymentMethodEpic = (action$: any, store: ReduxState) =>
  action$.ofType(CREATE_PAYMENT_METHOD)
    .switchMap(({ getBraintreeToken }) => Observable.fromPromise(getBraintreeToken()))
    .switchMap(({ nonce }) =>
      ajax(api.createPaymentMethod(store.billings.info.customer_id, nonce))
        .mapSuccess(CREATE_PAYMENT_METHOD)
        .mapFailure(CREATE_PAYMENT_METHOD),
    )
    .catch(mapBraintreeError);

我所做的是故意让getBraintreeToken()承诺失败。这会导致epic执行catch函数并返回CREATE_PAYMENT_METHOD + FAILURE操作。这就是我的意图。

问题是当我第二次尝试打电话给史诗时。它没有执行......

修改 我已经转换了史诗,现在似乎工作了,但是,我仍然不明白为什么第一个例子被打破了(实际上我更喜欢第一部史诗的平面结构)。

export const createPaymentMethodEpic = (action$: any, store: ReduxState) =>
  action$.ofType(CREATE_PAYMENT_METHOD)
    .switchMap(({ getBraintreeToken }) =>
      Observable.fromPromise(getBraintreeToken())
        .switchMap(({ nonce }) =>
          ajax(api.createPaymentMethod(store.billings.info.customer_id, nonce))
            .mapSuccess(CREATE_PAYMENT_METHOD)
            .mapFailure(CREATE_PAYMENT_METHOD),
        )
        .catch(mapBraintreeError),
    );

1 个答案:

答案 0 :(得分:1)

第一个版本的问题是error通知到达switchMap运算符,该运算符调用其错误逻辑导致链处理。

它必须是这样的,因为Observable会发出零或一个error通知,但绝不会更多。

有关详细说明,请参阅The Observable Contract

  

Observable可以制作零个或多个OnNext通知,每个通知代表一个发出的项目,然后它可以通过OnCompleted或OnError通知跟踪这些发射通知,但不能同时通过两者。 发出OnCompleted或OnError通知后,可能不再发出任何其他通知

在代码的第二个版本中,您将catch运算符置于switchMap的回调中。此处也应用了一个error通知规则,但是为每个值调用了回调,因此即使内部Observable发出错误,它也会被捕获(并转换为next),然后被新的替换内部可观察。