marius
marius

Reputation: 1613

How to cancel switchmap chain in RxJS?

The following use of switchMap...

Rx.Observable.timer(0, 1000)

  // First switchMap
  .switchMap(i => {
    if (i % 2 === 0) {
      console.log(i, 'is even, continue');
      return Rx.Observable.of(i);
    }
    console.log(i, 'is odd, cancel');
    return Rx.Observable.empty();
  })

  // Second switchMap
  .switchMap(i => Rx.Observable.timer(0, 500).mapTo(i))

  .subscribe(i => console.log(i));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>

... produces the following output:

0 is even, continue
0
0
1 is odd, cancel
0 // <-------------------- why?
0 // <-------------------- why?
2 is even, continue
2
2
3 is odd, cancel
2 // <-------------------- why?
2 // <-------------------- why?
4 is even, continue
.
.
.

I would expect the following output:

0 is even, continue
0
0
1 is odd, cancel
2 is even, continue
2
2
3 is odd, cancel
4 is even, continue
.
.
.

I expected that the first switchMap would cancel everything downstream, every time it returns, which I guess was incorrect.

Is there a way to achieve the desired behavior?

Upvotes: 2

Views: 4680

Answers (1)

Ruan Mendes
Ruan Mendes

Reputation: 92274

The reason is that returning an empty observable does not cause it switch to the new observable, that is the second switchMap never gets called.

A really hacky solution would be to return a magic value that you can ignore later

const CANCEL = {};
Rx.Observable.timer(0, 1000)

  // First switchMap
  .switchMap(i => {
    if (i % 2 === 0) {
      console.log(i, 'is even, continue');
      return Rx.Observable.of(i);
    }
    console.log(i, 'is odd, send CANCEL observable');
    return Rx.Observable.of(CANCEL);
  })


  // Second switchMap
  .switchMap(i => Rx.Observable.timer(0, 500).mapTo(i))

  // Filter out cancelled events
  .filter(i => i != CANCEL)
  
  .subscribe(i => console.log(i));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>

Upvotes: 2

Related Questions