5

I have two observables one$ and two$;

I want one$ only to fire when two$ has been fired at least once. This I think is essentially the skipUntil operator.

one$.skipUntil(two$).subscribe()

But let's say one$ has fired while two$ hasn't. I want a behaviour where the stream remembers that one$ has fired and will fire at least once, as soon as two$ did.

Cheers

martin
  • 93,354
  • 25
  • 191
  • 226
Han Che
  • 8,239
  • 19
  • 70
  • 116

3 Answers3

4

This looks like you can use the zip() operator that emits the nth item only when all its source Observables have emitted nth item:

const one$ = Observable.from(['a1', 'a2', 'a3'], Scheduler.async);
const two$ = Observable.from(['b1'], Scheduler.async);

Observable.zip(one$, two$, (v1, v2) => v1)
  .subscribe(val => console.log(val));

I'm adding Scheduler.async only to simulate asynchronous behavior (for more info see combineLatest behaviour in Rxjs 5?)

This will print to console:

a1

This is ok only if you know the one$ will emit only once.

Eventually you can use combineLatest() that needs all its source Observables to emit at least one item and then emits on any emission where you can ignore two$ with a selector function.

const one$ = Observable.from(['a1', 'a2', 'a3'], Scheduler.async);
const two$ = Observable.from(['b1', 'b2'], Scheduler.async);

Observable.combineLatest(one$, two$.take(1), (v1, v2) => v1)
  .subscribe(val => console.log(val));

We know that we only want the first item from two$, the rest can be ignored.
This will print to console:

a1
a2
a3
Community
  • 1
  • 1
martin
  • 93,354
  • 25
  • 191
  • 226
1

CombineLatest does what you want. You only need to provide a projector function:

one$.combineLatest(two$, v1 => v1).subscribe(x => console.log(x));

combineLatest waits until all observables have emitted at least one value, and then emits the combination of the last values of each observable. In your case, you only want the value from one observable. That's the reason to use the projector function. This projector function receives each observable value in one param and returns the value that will be emitted.

See an example in CodePen: https://codepen.io/sanzante/pen/vjMKwg

Also, check combineLatest behaviour in RxMarbles.

And the official documentation for combineLatest.

sanzante
  • 844
  • 1
  • 11
  • 28
0

combineLatest is exactly what you want. This operator will not emit an initial value until each observable emits at least one value.

combineLatest(([one$, two$])).subscribe(([one, two]) => {
  // do what you want with those values (or value one as you wish)
})
Anh Hoang
  • 2,242
  • 3
  • 22
  • 23