combineLatest的变体,当第一个observables作为参数传递完成时完成

时间:2018-04-25 06:59:23

标签: rxjs reactive-programming

combineLatest运算符返回一个Observable,该Observable在作为combineLatest的参数传入的所有observable完成时完成。

有没有办法创建一个Observable,其行为与combineLatest返回的一样,唯一的区别是当Observables的第一个作为参数完成时完成?

2 个答案:

答案 0 :(得分:2)

是的,你可以;你可以这样做:



function combineLatestUntilFirstComplete(...args) {
  const shared = args.map(a => a.share());
  return Rx.Observable
    .combineLatest(...shared)
    .takeUntil(Rx.Observable.merge(...shared.map(s => s.last())));
}

const a = Rx.Observable.interval(100).map(index => `a${index}`).take(5);
const b = Rx.Observable.interval(200).map(index => `b${index}`).take(5);

combineLatestUntilFirstComplete(a, b).subscribe(
  value => console.log(JSON.stringify(value)),
  error => console.error(error),
  () => console.log("complete")
);

.as-console-wrapper { max-height: 100% !important; top: 0; }

<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
&#13;
&#13;

实现从内部调用返回的observable中取值combineLatest,直到其中一个源observable发出最后一个值。

请注意,源可观察对象是共享的,因此takeUntil调用导致的订阅不会影响对冷源可观察对象的二次订阅。

答案 1 :(得分:2)

const a = Rx.Observable.interval(400).share();
const b = Rx.Observable.interval(600).share();
const c = Rx.Observable.interval(1000).take(3).share();

const combined = Rx.Observable.combineLatest(a, b, c)
  .takeUntil(
    Rx.Observable.merge(
      a.ignoreElements().concat(Rx.Observable.of('fin-a')).do(console.log),
      b.ignoreElements().concat(Rx.Observable.of('fin-b')).do(console.log),
      c.ignoreElements().concat(Rx.Observable.of('fin-c')).do(console.log)
    )
  );

combined
  .subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.10/Rx.js"></script>

您需要.share()输入可观察量,因为您需要两次,一次用于.combineLatest(),一次用于.takeUntil来完成您的可观察流。

我使用.ignoreElements()中的.takeUntil忽略任何值,并且仅在源流(abc)完成时才会.concat向其发送“最终”消息,通知.takeUntil完成对.combineLatest的订阅。如果a,b,c不发出任何值,这也可以。