Reputation: 621
I need to run sequentially two observables and returns the result of the first observable only. The second observable needs the first to be completed before running.
I found a workaround but I'm not satisfied. You can test it here : plunker test
const first = Observable.of(10).delay(1000).do(res => console.log('first'));
const second = Observable.of(20).do(res => console.log('second'));
console.log('start');
const test = first.concatMap(ev => second.map(x=> ev)).subscribe(res =>
console.log(res));
I think (and I hope !) a nicer solution exists but I can't find it. Thanks in advance for your help.
Upvotes: 5
Views: 2319
Reputation: 589
const test = first
.pipe(
delayWhen(() => second)
)
.subscribe(() => {
...
});
This should execute both the first and second observables in order but only emit the result of the first observable after the result from the second observable is emitted internally.
Upvotes: 0
Reputation: 81
I'm not sure, but I think you could use concatMapTo. See Example 2. In your case:
const first$ = of(10).pipe(delay(1000),tap(res => console.log('first')));
const second$ = of(20).pipe(tap(res => console.log('second')));
const test = first$.pipe(
concatMapTo(
second$,
(first, second) => first
)
);
test.subscribe(res => console.log(res));
https://stackblitz.com/edit/typescript-xrmsy5
If you want to manage more observables you could use switchMap/mergeMap. For example
const test = first$.pipe(
// map(e => { if(e === '1') throw e; return e; } ), //throwing invalid result
switchMap(e => second$, (f,s) => {console.log('switchMap',f,s); return f;}),
switchMap(e => trird$, (f,s) => {console.log('switchMap', f,s); return f;}),
);
https://stackblitz.com/edit/typescript-mnsd8a
Upvotes: 1
Reputation: 17859
User merge
with take(1)
:
Observable.merge(first, second).take(1).subscribe(x=>console.log(x));
Upvotes: 0
Reputation: 43797
I internally translate flatMap
to then
in my head so I would expect to see something like...
const first = Observable.of(10).delay(1000).do(res => console.log('first'));
const second = Observable.of(20).do(res => console.log('second'));
const test = first.flatMap(rsp => { return second.mapTo(rsp); });
It isn't really any different than what you posted but it would make more sense to me intuitively since I wouldn't start thinking about the concat
operation.
Update:
I suppose you could also do...
const test = first.delayWhen(() => second.mapTo(0));
...but I'm not sure if that is more readable.
Upvotes: 2