SylphFeather
SylphFeather

Reputation: 435

How to have an observable return values one after another

Is there an rxjs function / other way to do this (where is a function that hopefully exists):

    let testOb$ = of(4).pipe(
      <???>(input => of(input + 2)),
      <???>(input => of(input - 3))
    )
    testOb$.subscribe(x => console.log(x))

    // logs 4, then 6, then 3
    // switchMap and mergeMap just returns 3

Note that the values should come one after another, and not complete all at once, then log the 3 values separately.

Use case:

I want to load some troublesome data consisting of an array of objects.

Each of the objects has a single value that is too large, and if loaded all together, causes significant lag. But so long as one is loaded first, there's no UI lag.

So I would like to:

data$ = this._store.dispatch(fetchInitial())
    .pipe(
        <???>(data => fillInitial(data))
        <???>(data => fillRemainder(data))
    )
data$.subscribe(data => renderInput(data))

Is this a valid approach?

If not, what is considered best practice for this kind of use case with rxjs?

Upvotes: 0

Views: 523

Answers (2)

Maksim Romanenko
Maksim Romanenko

Reputation: 365

Create 3 separate streams and merge when you need.

   let testOb$ = of(4).pipe(share());

   const six$ = testOb$.pipe(mergeMap(input => of(input + 2)));
   const three$ = testOb$.pipe(mergeMap((input => of(input - 3)));

   merge(testOb$, six$, three$).subscribe(x => console.log(x))

Upvotes: 0

ggradnig
ggradnig

Reputation: 14149

Your desired output can be achieved like this:

let testOb$ = of(4).pipe(
  mergeMap(input => from([input, input + 2])),
  mergeMap(input => from([input, input - 3])),
  filter((val, index) => index != 1)
);
testOb$.subscribe(x => console.log(x))

It looks weird because your desired output doesn't really follow a simple rule. But it works.

https://stackblitz.com/edit/rxjs-cmxgan?devtoolsheight=60

Now, for your second example, we would do something like this to avoid the delay:

data$ = this._store.dispatch(fetchInitial())
  .pipe(
    mergeMap(data => fillInitial(data).pipe(startWith(data)))
    mergeMap(data => fillRemainder(data).pipe(startWith(data))),
    filter((val, index) => index != 1)
)

Upvotes: 2

Related Questions