Home > Enterprise >  Piped observable not emitting when source emits
Piped observable not emitting when source emits

Time:12-20

public lotId$ = new Subject<number>();

@Input() public set lotId(value: number) {
    this.lotId$.next(value);
};

public results$ = this.lotId$.asObservable().pipe(
    skipWhile(lotId => !lotId),
    switchMap(lotId => this.logicService.getMappedTakeOffTasksForLot(lotId)),
    tap(console.log)
);

In the code above, results$ does not emit every time lotId$ emits. Anyone know why? the code runs over results$ once when the component is created and then never again.

EDIT: The source emits 58.

EDIT: It works when I change from Subject to BehaviorSubject. Why? I wish I tried that sooner.

CodePudding user response:

results$ does not emit every time lotId$ emits.

Subscriptions to results$ that occur before lotId$ emits, will receive those values. To put it another way, late subscribers don't receive prior values (by "late subscriber" I mean subscription after some emissions have occurred).

Assuming you are using async pipe in your template, the subscription of results$ doesn't happen until after the view has been initialized, but the @Input() setters are called before that happens.

You will find that if you subscribe in the constructor (just for experimentation), the derived results$ will in fact emit the initial values.

So, it should be clear why changing to compare behavior of different subject types

If a component has an optional @Input(), I use BehaviorSubject since a default value is needed. If the input is required I use ReplaySubject(1), so my logic is not executed unless the consumer provides the input.

Here's a little StackBlitz where you can see the order of the Angular lifecycle hooks and when the subscriptions occur.

  • Related