我不知道我的题目是否适合这个问题。我希望使用someAsync1的返回值(与v2相同)作为action1在flatMap中的参数。
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => someAsync2(v2))
.map((v) => applyToUI(v))
.flatMap((v) => Observable.concat(Observable.of(action1(v)), Observable.of(action2(true)))) //
}我想我可以通过将v2注入someAsync2的返回值来使用这个值。但那密码看起来很恶心。有什么聪明的方法可以通过可观察到的方法来实现呢?
发布于 2018-01-03 03:29:52
从技术上讲,switchMap意味着,将切换到另一个可观察到的流。这意味着你没有办法保留这个值,因为你的观察者现在正在观察一个不同的来源。
有几种方法可以实现所谓的“保留”从一个流到另一个流的值,这取决于您喜欢哪个流。
1.行为主体
这是最首选的方法,因为BehaviourSubject的目的是保留Observable的值。
//initialize a BehaviourSubject
let v2BSubject = new BehaviourSubject<any>(null);
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => {
//store your v2 value here!
v2BSubject.next(v2);
return someAsync2(v2)
})
.map((v) => applyToUI(v))
.flatMap((v) => {
//get your v2 values here
let v2Value = v2BSubject.value;
return Observable.concat(Observable.of(action1(v)), Observable.of(action2(true)))
}) //
}或者您可以使用它作为一个Observable。这样,您就可以将其视为可观察的,并使用rxjs操作符可以提供的任何内容:
.flatMap((v) => {
return Observable.concat(Observable.of(action1(v)), v2BSubject.asObservable())
}) 2.使用.map来传播该值。
这很烦人,但能把工作做完。但是,请注意,它正在修改流源。如果你在管道上有很多操作,它可能会很快爆炸,而且很难管理:
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => {
someAsync2(v2)
.map(afterSomeAsync2 => {
return {
v1Value: v2,
v2Value: afterSomeAsync2
}
})
})
.map(({v1Value, v2Value}) => {
return applyToUI(v1Value).map(v1 => {
return {
v1Value: v1,
v2Value: v2Value
}
})
})
.flatMap(({v1Value, v2Value}) => {
return Observable.concat(Observable.of(action1(v1Value)), Observable.of(v2Value))
}) 发布于 2018-01-04 19:33:41
最简单的解决方案是直接将运算符应用于返回的内部可观测值,而不是应用于折叠的外部链。然后,您可以访问发出的值,因为它们是闭包的一部分。
这可能会让人困惑,但希望这段代码能清楚地说明:
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) =>
someAsync1(v1)
.switchMap((v2) =>
someAsync2(v2)
.map((v) => applyToUI(v))
.flatMap((v) => Observable.of(action1(v, v1, v2), action2(true))
)
)
}如果希望通过someAsync1或someAsync2捕获任何错误,则必须使用此模式,因为如果让错误传播到顶级链,epic将停止侦听未来的操作。
例如,如果你的史诗像这样:
const somethingEpic = (action$, store) => {
return action$.ofType(SOMETHING)
.switchMap(action => someAsync1(v1))
.map(() => ({ type: SOMETHING_FULFILLED }))
.catch(error => Observable.of({
type: SOMETHING_REJECTED,
error
}));
}当错误到达catch操作符时为时已晚,您的epic将不再侦听未来的操作。您可以“重新启动”它,但这可能会产生意想不到的后果,因此最好避免这种模式。
相反,在错误传播之前捕获它。
const somethingEpic = (action$, store) => {
return action$.ofType(SOMETHING)
.switchMap(action =>
someAsync1(v1)
.map(() => ({ type: SOMETHING_FULFILLED }))
.catch(error => Observable.of({
type: SOMETHING_REJECTED,
error
}))
);
}有些人把这称为“孤立你的观察者锁链”。
还请注意,我不需要将concat与多个of一起使用,因为of支持任意数量的参数。
https://stackoverflow.com/questions/48066645
复制相似问题