Javascript 具有多个内部订阅的Rxjs嵌套订阅
我试图重写的基于承诺的原始代码:Javascript 具有多个内部订阅的Rxjs嵌套订阅,javascript,design-patterns,rxjs,Javascript,Design Patterns,Rxjs,我试图重写的基于承诺的原始代码: parentPromise .then((parentResult) => { childPromise1 .then(child1Result => child1Handler(parentResult, child1Result)); childPromise2 .then(child1Result => child2Handler(parentResu
parentPromise
.then((parentResult) => {
childPromise1
.then(child1Result => child1Handler(parentResult, child1Result));
childPromise2
.then(child1Result => child2Handler(parentResult, child2Result));
childPromise3
.then(child1Result => child3Handler(parentResult, child3Result));
});
我试图找出一种方法,在以下场景中如何避免:
parent$
.pipe(takeUntil(onDestroy$))
.subscribe((parentResult) => {
child1$
.pipe(takeUntil(onDestroy$))
.subscribe(child1Result => child1Handler(parentResult, child1Result));
child2$
.pipe(takeUntil(onDestroy$))
.subscribe(child2Result => child2Handler(parentResult, child2Result));
child3$
.pipe(takeUntil(onDestroy$))
.subscribe(child3Result => child3Handler(parentResult, child3Result));
});
正确的“RxJS方式”是什么?这对我来说似乎很奇怪。每次
parentResult
到达时,您都会为每个孩子创建新订阅。即使这些最终确实会被销毁(假设onDestroy$实现是正确的),但似乎是错误的
您可能希望使用最新的from(parent$)
并为每个子级使用三个单独的管道
它可能看起来像:
child1$.pipe(takeUntil(globalDeath$)、withLatestFrom(parent$).subscribe([childResult,parentResult])=>…)
。不确定我的JS是否正确,目前无法测试;但关键是:每次激发child1$
时,您都会从parent$
获得最新的结果。请注意,如有必要,您可以反转方向(使用最新from(child1$)
)。您可以:1)通过共享传递父$
,以及2)使用平面图
三次,例如:
const sharedParent$ = parent$.pipe(share());
sharedParent$.pipe(
flatMap(parentResult => forkJoin(of(parentResult), child1$)),
takeUntil(onDestroy$)),
.subscribe((results) => child1Handler(...results)); // repeat for all children
(如果有两个以上的子级,则最好将其提取到具有子流和处理程序作为参数的函数中)
这遵循了最初的行为,即与订阅子项一起等待,直到parent$
发出。如果您不需要它,您可以跳过flatMap
,只需forkJoin
sharedParent$
和子对象。使用更高阶的可观察对象怎么样?大概是这样的:
const parentReplay$ = parent$.pipe(shareReplay(1));
of(
[child1$, child1Handler],
[child2$, child2Handler],
[child3$, child3Handler]
).pipe(
mergeMap([child$, handler] => parentReplay$.pipe(
mergeMap(parentResult => child$.pipe(
tap(childResult => handler(parentResult, childResult))
)
)
).subscribe();
如果您使用的是承诺,那么相应的观测值只发射一次,然后完成
如果是这种情况,您可以使用forkJoin
并行执行子对象
所以代码可能看起来像
parent$.pipe(
takeUntil(onDestroy$),
// wait for parent$ to emit and then move on
// the following forkJoin executes the child observables in parallel and emit when all children complete - the value emitted is an array with the 3 notifications coming from the child observables
concatMap(parentResult => forkJoin(child1$, child2$, child3$)).pipe(
// map returns both the parent and the children notificiations
map(childrenResults => ({parentResult, childrenResults})
)
).subscribe(
({parentResult, childrenResults}) => {
child1Handler(parentResult, childrenResults[0]);
child1Handler(parentResult, childrenResults[1]);
child1Handler(parentResult, childrenResults[2]);
}
)
这将导致对父级的多个订阅,因此请确保这是可接受的,或者首先对其进行多播。