Summary of async


Rxjs is integrated into the Angular framework, and various business scenarios can be handled using Observables. For observables, see Angular documentation – Observable Overview.

Since observables are lazy, they need to be subscribed to actively trigger functions, and they need to recycle the Observer after subscribed. so Angular designs a pipe operator Async for observables.

Example of async usage


Here is an example to compare the benefits of using the Async pipeline:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subscription, fromEvent } from 'rxjs';
import { takeUntil, interval, map, map } from 'rxjs/operators';

@Component({
  selector: 'app-test',
  template: `CurrentTime: {{ time | date }}`
})
export class AppTestComponent implements OnInit, OnDestroy {
  time: Date;
  timeSubscription: Subscription;

  ngOnInit() {
    this.timeSubscription = Observable
      .interval(1000)
      .map(val => new Date())
      .subscribe(val => this.time = val);
  }

  ngOnDestroy() { this.timeSubscription.unsubscribe(); }}Copy the code

In the code snippet above, we take a value every 1000 ms using the interval operator and map it to the current timestamp using the map operator. By changing the time variable to achieve page timing function.

During the component destruction phase, we recycle this Observer.

This is quite a bit of boilerplate code, and we run the risk of a memory leak if we forget to unsubscribe

We can greatly simplify here the Async pipeline to achieve the same function:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subscription, fromEvent } from 'rxjs';
import { takeUntil, interval, map, map } from 'rxjs/operators';

@Component({
  selector: 'app-test',
  template: `Time: {{ time$ | async | date }}`
})
export class AppTestComponent {
  time$ = Observable
    .interval(1000)
    .map(val => new Date());
}

Copy the code

The Async Pipe is responsible for subscriptions and change detection, as well as unsubscribing when a component is destroyed. An operator saves a lot of code dealing with Observable problems.

In practical development, the async pipeline should be selected to solve similar problems and keep the code concise. However, in the case of combined streams and high-order streams, the Async pipeline is powerless.

The $character is a default angular rule. Any object or variable that contains the § character is an Observable by default.

Async official source code


The Async pipe operator helps us actively subscribe to an Observable, get the latest value, and trigger change detection. AsyncPipe also helps us to unsubscribe when a component is destroyed, avoiding memory leaks. In practice, we can already guess how it works:

The following source is from the Angular repository

@Pipe({name: 'async', pure: false})
exportclass AsyncPipe implements OnDestroy, PipeTransform { private _latestValue: any = null; private _latestReturnedValue: any = null; . Constructor (private _ref: ChangeDetectorRef) {} ngOnDestroy(): voidif (this._subscription) {
      this._dispose();
    }
  }
  
  transform(obj: Observable<any>|Promise<any>|null|undefined): any {
    if(! this._obj) {if(obj) {this._subscribe(obj) {// Subscribe to the incoming Observable; } this._latestReturnedValue = this._latestValue;returnthis._latestValue; }... } private _subscribe(obj: Observable<any>|Promise<any>|EventEmitter<any>): void { this._obj = obj; this._strategy = this._selectStrategy(obj); / / save the subscription object, and perform markForCheck testing this. _subscription = this. _strategy. CreateSubscription (obj, (value: Object) => this._updateLatestValue(obj, value)); }... private _dispose(): void { this._strategy.dispose(this._subscription !) ; this._latestValue = null; this._latestReturnedValue = null; this._subscription = null; this._obj = null; } private _updateLatestValue(async: any, value: Object): void {if(async === this._obj) { this._latestValue = value; this._ref.markForCheck(); }}}Copy the code

The Async pipe handles a lot of the hassle of using an Observable, so in actual business scenarios Async pipe should be used more to manage our data.

More examples of async


Since Many Angular business flows can be handled by observables. The Async operator is naturally used extensively in projects, and can be used in combination with many scenarios:

  • Used in parent component arguments:
    <home-risk-card [CardModel] ="item | async"></home-risk-card>
Copy the code
  • Combined with *ngFor, *ngIf and other commands:
    <nz-col *ngFor="let item of riskData$ | async" [nzSpan] ="8">
        <home-risk-card [CardModel] ="item"></home-risk-card>
    </nz-col>
    
    <div class="app-test"  *ngIf="(riskData$ | async)? .length > 0"></div>
Copy the code
  • To use in combination with variables:
    <ng-container *ngIf="info$ | async as info">
      <h1>{{info.titile}}</h1>
      <div>
        {{info.content}}
      </div>
    </ng-container>
Copy the code
  • Used in conjunction with @ngrx/store:
.@Component({
  selector: 'app-test2',
  template: ` 
       `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TestComponent {
  infoList$: Observable<Info[]>;

  constructor(store: Store<AppState>) {
    this.infoList$ = store.select(getInfoListSelector); }... }Copy the code

I hope I can help you.

Thank you for reading ~