Why is this tap operator not firing?

Viewed 1586

I'm puzzled by this rxjs tap() operator never firing in this simple Angular component, while the Subject value does get updated on the screen. I also tried using a BehaviorSubject instead with the same results. What I'm I doing wrong here?

import { Component } from '@angular/core';

import { Subject, BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  template: '{{ selectedUserId | async }}',
})
export class AppComponent { 

  selectedUserId = new Subject<number>();
  // selectedUserId = new BehaviorSubject<number>(0);

  ngOnInit() {
    this.selectedUserId
      .pipe(
        tap(id => console.log(id)) // why this is not logging to console?
      );
    setTimeout(() => this.selectedUserId.next(1), 1000);
    //this.selectedUserId.next(1);
  }

}
2 Answers

That's because the Observable the async pipe subscribes to doesn't have a tap.

Specifically, the pipe operator in

this.selectedUserId
  .pipe(
    tap(id => console.log(id)) // why this is not logging to console?
  );

doesn't modify the Observable stored in this.selectedUserId. Rather, it creates and returns a new Observable with the tap, but since you never subscribe to the returned Observable the tap is never called ...

this line this.selectedUserId.pipe(tap(id => console.log(id)) ); return an new observable base of selectedUserId so you need to subscribe to new observable the start get the values and .

tab operater will work on the new observable and not effected the base observable (selectedUserId)

  const obs =  this.selectedUserId
      .pipe(
        tap(id => console.log(id)) 
      );

   obs.subscribe()

demo

to make it clear the new observable will be run by async pipe , not that the values of observable will change base of the subject observable during the time

  private selectedUserId = new Subject<number>();
  public userId$ : Observable<number>;

  ngOnInit() {
   this.userId$ =  this.selectedUserId
      .pipe(
        tap(id => console.log(id)) ,
      );

    setTimeout(() => this.selectedUserId.next(1), 1000);
    setTimeout(() => this.selectedUserId.next(2), 2500);
    setTimeout(() => this.selectedUserId.next(3), 5000);
  }

template

{{ userId$ | async }}

demo

Related