ABOS
ABOS

Reputation: 3823

how does async pipe know when to update

I have the following code to manage users,

@Component({
  selector: 'app-user',
  template: `
  <input [(ngModel)]="newUser"><button (click)="addNewUser()">add</button>
  <div *ngFor="let user of users$ |async">
    {{user}}
  </div>
  `
})
export class UserComponent {
  newUser: string;
  users$: Observable<any>;
  private _users = [];

  ngOnInit() {
    this.users$ = of(this._users);
  }

  addNewUser() {
    this._users.push(this.newUser);
  }
}

How does angular know when to update this.users$ in the html when I simply push a new user to this._users array wrapped in rxjs of? How does angular async pipe detect changes inside an observable?

Upvotes: 2

Views: 11805

Answers (1)

Adrian Brand
Adrian Brand

Reputation: 21628

You can view the source code here

https://github.com/angular/angular/blob/master/packages/common/src/pipes/async_pipe.ts

It subscribes to the observable.

From the comments in the source

  • Unwraps a value from an asynchronous primitive.
  • The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted.
  • When a new value is emitted, the async pipe marks the component to be checked for changes.
  • When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

Looking at your question you are abusing the point of observables. You should not be pushing a new value into the array, you should be making the observable emit a new array. The reason Angular is updating the page has nothing to do with observables but the fact you are using the default change detection strategy it notices the array has changed.

If you were using a BehaviorSubject instead of using of you could call next

addNewUser() {
  const users = this.users$.getValue();
  this.users$.next([...users, this.newUser]);
}

Observables allow you to use the more efficient on push change detection strategy which will not update the page with what you have done. You would need to replace the array with a new instance of an array for onPush to detect changes.

Upvotes: 5

Related Questions