Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the Observable operator takeUntil() depend upon it's order in pipe()

Is the operator takeUntil affected by other operators, and do you have to use it twice inside a switchMap?

For example;

Assume that I have an observable that emits a value when I no longer want to subscribe, and we'll refer to this as this._destroyed.

Does it matter if there is a delay operator before a takeUntil?

 of("something").pipe(
      delay(1000),
      takeUntil(this._destroyed)
 );

Is the above any different from reversing the order?

 of("something").pipe(
      takeUntil(this._destroyed),
      delay(1000)
 );

What if I use switchMap do I have to call takeUntil twice?

 of("something").pipe(
      takeUntil(this._destroyed),
      delay(1000),
      switchMap(() => {
          return of("other").pipe(
             takeUntil(this._destroyed),
             delay(1000)
          );
      }
 );

Is the above functionally the same as calling takeUntil once?

 of("something").pipe(
      delay(1000),
      switchMap(() => {
          return of("other").pipe(delay(1000));
      }),
      takeUntil(this._destroyed)
 );

I guess I'm confused as to what happens when takeUntil is triggered and stops the current subscription. How is it impacted by when it is called in the pipe order (if there is any impact at all).

like image 918
Reactgular Avatar asked Sep 01 '18 19:09

Reactgular


People also ask

Where should takeUntil be placed?

The general rule is for takeUntil to be placed last. However, there are some situations in which you might want want use it as the second-last operator. RxJS includes several operators that emit a value when the source observable to which they are applied completes.

Does takeUntil complete the observable?

The takeUntil operator returns an Observable that emits value from the source Observable until the notifier Observable emits a value. When the notifier emits a value, the TakeUntil completes the Source observable.

What is pipe takeUntil?

pipe(takeUntil(this. onDestroy$)) . subscribe((message: any) => { some code here; } takeUntil is a function in a component to unsubscribe when component is destroyed.


1 Answers

My understanding is that generally takeUntil should be the last operator in a chain because it can result in leaks. This article describes the issue: https://ncjamieson.com/avoiding-takeuntil-leaks/

The article uses the following example:

import { combineLatest, Observable } from "rxjs";
import { takeUntil } from "rxjs/operators";

declare const a: Observable<number>;
declare const b: Observable<number>;
declare const notifier: Observable<any>;

const c = a.pipe(
  takeUntil(notifier),
  o => combineLatest(o, b)
).subscribe(value => console.log(value));

From the article:

When the notifier emits, the observable returned by the takeUntil operator completes, automatically unsubscribing any subscribers.

However, the subscriber to c is not subscribed to the observable returned by takeUntil — it’s subscribed to the observable returned by combineLatest — so it’s not automatically unsubscribed upon the takeUntil observable’s completion.

The subscriber to c will remain subscribed until all of the observables passed to combinedLast complete. So, unless b completed before the notifier emitted, the subscription to b would leak.

While this post specifically refers to switchMap, I suspect the logic is the same. It may be less of an issue with switchMap, as there is only one inner observable.

like image 150
rfestag Avatar answered Sep 28 '22 20:09

rfestag