How to make one Observable sequence wait for another to complete before emitting?
A couple ways I can think of
import {take, publish} from 'rxjs/operators'import {concat} from 'rxjs'//Method onevar one = someObservable.pipe(take(1));var two = someOtherObservable.pipe(take(1));concat(one, two).subscribe(function() {/*do something */});//Method two, if they need to be separate for some reasonvar one = someObservable.pipe(take(1));var two = someOtherObservable.pipe(take(1), publish());two.subscribe(function(){/*do something */});one.subscribe(function(){/*do something */}, null, two.connect.bind(two));
skipUntil() with last()
skipUntil : ignore emitted items until another observable has emitted
last: emit last value from a sequence (i.e. wait until it completes then emit)
Note that anything emitted from the observable passed to skipUntil
will cancel the skipping, which is why we need to add last()
- to wait for the stream to complete.
main$.skipUntil(sequence2$.pipe(last()))
Official: https://rxjs-dev.firebaseapp.com/api/operators/skipUntil
Possible issue: Note that last()
by itself will error if nothing is emitted. The last()
operator does have a default
parameter but only when used in conjunction with a predicate. I think if this situation is a problem for you (if sequence2$
may complete without emitting) then one of these should work (currently untested):
main$.skipUntil(sequence2$.pipe(defaultIfEmpty(undefined), last()))main$.skipUntil(sequence2$.pipe(last(), catchError(() => of(undefined))
Note that undefined
is a valid item to be emitted, but could actually be any value. Also note that this is the pipe attached to sequence2$
and not the main$
pipe.
If you want to make sure that the order of execution is retained you can use flatMap as the following example
const first = Rx.Observable.of(1).delay(1000).do(i => console.log(i));const second = Rx.Observable.of(11).delay(500).do(i => console.log(i));const third = Rx.Observable.of(111).do(i => console.log(i));first .flatMap(() => second) .flatMap(() => third) .subscribe(()=> console.log('finished'));
The outcome would be:
"1""11""111""finished"