Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS operators execution order

Considering I have the following code:

private readonly postAction$ = new Subject();

postStream$ = this.postAction$.pipe(
    exhaustMap(() => {
      this.count ++;
      console.log('fired')
      return of('my other post');
    }),
    startWith(''),
    exhaustMap(()=> {
      this.count ++;
      console.log('fired first')
      return of('my post' + this.count);
    })
  )

Which I subscribe to in my template using the async pipe.

I wasn't expecting this to work, but the output to the console was:

> fired first

Until I call .next() on the postAction$ subject, the first console.log('fired') is never called.

What's the execution context of RxJS operators? How do they work? I would have expected that the first exhaust map needed to emit a value, before the rest of the operators are ran. Couldn't find anything in the rxjs docs

Demo on stackblitz

like image 589
C_Ogoo Avatar asked Jun 08 '26 03:06

C_Ogoo


1 Answers

I think the best way to find the answer is to actually see what's going on behind the scenes(I haven't done that, but I hope to do so in the future).

Until then, here is how I see things.

Think of a stream as river.
The river is traversed by boats, which basically are the emitted values.
There are also bridges, you can think of them as operators. Each bridge might require some conditions in order to decide which boat can continue its way and which not.

Here is how I'd visualize it:

            The value from `startWith`
                     ↓
~~~~~~~~|~~~~~~~~|~~~B~~~~|~~~~~~~~

        ^        ^        ^
        |        |    `exhaustMap(() => {})`
        |        |
        |   `startWith('B')`
        |
`exhaustMap(() => {})`

The async pipe internally subscribes to(and unsubscribes from) the given observable. I think of the subscription as the process of setting up the river, and the bridges. There are no boats yet.
But, in this case, a boat can start from the second bridge, which means that the first one will have nothing to say about this.

This, if you place the bridges this way:

 postStream$ = this.postAction$.pipe(
    startWith(''),
    exhaustMap(() => {
      this.count ++;
      console.log('fired')
      return of('my other post');
    }),
    exhaustMap(()=> {
      this.count ++;
      console.log('fired first')
      return of('my post' + this.count);
    })
  )

You should see this output in the console:

fired
fired first
like image 165
Andrei Gătej Avatar answered Jun 10 '26 05:06

Andrei Gătej



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!