Karine
Karine

Reputation: 621

Rxjs Returns first result of two observables run sequentially

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

Answers (4)

boylec1986
boylec1986

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

Alex Walker
Alex Walker

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

Julia Passynkova
Julia Passynkova

Reputation: 17859

User merge with take(1):

Observable.merge(first, second).take(1).subscribe(x=>console.log(x));

Upvotes: 0

Pace
Pace

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

Related Questions