简体   繁体   English

RxJS combineLatest 每个路径只发射一次

[英]RxJS combineLatest emit only once per path

Is there any way/pattern to use combineLatest() or some other operator so that if the combined observables depend on one another, they will only emit only once for each set of paths with the same origin in a DAG?有没有什么方法/模式可以使用combineLatest()或其他一些运算符,这样如果组合的可观察对象相互依赖,它们只会为 DAG 中具有相同来源的每组路径只发射一次? I think it may be easier to explain with a diagram.我认为用图表解释可能更容易。

Diagram:图表:

   A C
  /| |
 B | |
  \|/
   D

Here B is subscribed to A, and D is subscribed to A, B, and C. The default behavior is that if A emits, D emits twice : once when A emits, and once more when B emits (as a result of A emitting).这里 B 订阅了 A,D 订阅了 A、B 和 C。默认行为是如果 A 发射,D 发射两次:一次是 A 发射,一次是 B 发射(作为 A 发射的结果). I would like it to emit only once , after both have emitted.我希望它只发射一次,在两者都发射之后。 However, if C emits, then D should emit immediately as well.但是,如果 C 发射,那么 D 也应该立即发射。

Here's the code:这是代码:

const A = new Rx.BehaviorSubject(1);
const B = A.pipe(Rx.map((x) => x + 1));
const C = new Rx.BehaviorSubject(3);

const D = Rx.combineLatest({ A, B, C });

D.subscribe(console.log); // {A: 1, B: 2, C: 3}
A.next(2); // Two emissions: {A: 2, B: 2, C: 3}, {A: 2, B: 3, C: 3} 
// Would like the second one ONLY, i.e. {A: 2, B: 3, C: 3}
C.next(4); // Correctly emits: {A: 2, B: 3, C: 4}

One solution I've tried is to linearize it and make the entire collection of A, B, and C an observable:我尝试过的一种解决方案是将其线性化并使 A、B 和 C 的整个集合成为可观察的:

 {A, C}
    |
{A, C, B}
    |
   {D}

This works but I wonder if there's perhaps a better way.这行得通,但我想知道是否有更好的方法。

If I understand right the question, you want that the final Observable D emits any time either A (the upstream of B ) or C emit but, if A emits, you want also the value emitted by B .如果我理解正确的问题,您希望最终的 Observable D随时发出AB的上游)或C发出,但是,如果A发出,您还需要B发出的值。

If this is the case, I would make sure that any time B emits, it emits not only the value of B but also the value notified by its upstream A , and then I would pass to combineLatest only B and C , like this如果是这种情况,我将确保任何时候B发出,它不仅发出B的值,还发出其上游A通知的值,然后我将仅传递给combineLatest BC ,就像这样

const A = new BehaviorSubject(1);
const B = A.pipe(map((x) => [x, x + 1]));
const C = new BehaviorSubject(3);

const D = combineLatest({ B, C }).pipe(
  map((val) => ({ A: val.B[0], B: val.B[1], C: val.C }))
);

you can zip A,B, together so for every pair of emissions you get only one in D. Combine that with C which is just one:您可以将zip A、B 放在一起,因此对于每一对发射,您只能在 D 中得到一个。将其与 C 结合起来,这只是一个:

const A = new BehaviorSubject(1);
const B = A.pipe(map((x) => [x, x + 1]));
const C = new BehaviorSubject(3);


const D = combineLatest({ zip(A,B), C })

This requires both A & B to emit a value but because those depend on eachother that is not an issue in your example.这需要 A 和 B 都发出一个值,但是因为它们相互依赖,所以在您的示例中这不是问题。

https://www.learnrxjs.io/learn-rxjs/operators/combination/zip https://www.learnrxjs.io/learn-rxjs/operators/combination/zip

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM