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]);
  }
)

这将导致对父级的多个订阅,因此请确保这是可接受的,或者首先对其进行多播。