redux-observable 和 rxjs。将 promise 转换为 Observable - epic 只被调用一次
redux-observable and rxjs. Converting promise to Observable - epic gets called only once
我正在使用 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()
Promise 失败。这导致史诗执行 catch
函数并返回 CREATE_PAYMENT_METHOD + FAILURE
操作。这正是我想要的。
问题出在我第二次尝试调用 epic 时。它不执行...
编辑:
我已经转换了史诗并且它现在似乎可以工作,但是,我仍然不明白为什么第一个例子被破坏了(实际上我更喜欢第一个史诗的扁平结构)。
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),
);
第一个版本的问题是 error
通知到达 switchMap
运算符,该运算符调用其导致链处理的错误逻辑。
它需要像这样,因为 Observable 发出零个或一个 error
通知,但不会更多。
有关更详细的说明,请参阅 The Observable Contract。
An Observable may make zero or more OnNext notifications, each representing a single emitted item, and it may then follow those emission notifications by either an OnCompleted or an OnError notification, but not both. Upon issuing an OnCompleted or OnError notification, it may not thereafter issue any further notifications.
在代码的第二个版本中,您将 catch
运算符放在 switchMap
的回调中。这里也应用了一个 error
通知规则,但是回调会为每个值调用,所以即使内部 Observable 发出错误,它也会被捕获(并转换为 next
),然后它被一个新的替换内部 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()
Promise 失败。这导致史诗执行 catch
函数并返回 CREATE_PAYMENT_METHOD + FAILURE
操作。这正是我想要的。
问题出在我第二次尝试调用 epic 时。它不执行...
编辑: 我已经转换了史诗并且它现在似乎可以工作,但是,我仍然不明白为什么第一个例子被破坏了(实际上我更喜欢第一个史诗的扁平结构)。
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),
);
第一个版本的问题是 error
通知到达 switchMap
运算符,该运算符调用其导致链处理的错误逻辑。
它需要像这样,因为 Observable 发出零个或一个 error
通知,但不会更多。
有关更详细的说明,请参阅 The Observable Contract。
An Observable may make zero or more OnNext notifications, each representing a single emitted item, and it may then follow those emission notifications by either an OnCompleted or an OnError notification, but not both. Upon issuing an OnCompleted or OnError notification, it may not thereafter issue any further notifications.
在代码的第二个版本中,您将 catch
运算符放在 switchMap
的回调中。这里也应用了一个 error
通知规则,但是回调会为每个值调用,所以即使内部 Observable 发出错误,它也会被捕获(并转换为 next
),然后它被一个新的替换内部 Observable。