Angular2 AsyncPipe

劳星晖
2023-12-01

今天我们来介绍一下 Angular 2 中 AsyncPipe (异步管道) ,使用 AsyncPipe 我们可以直接在模板中使用 PromiseObservable 对象,而不用通过定义一个类的成员属性来存储返回的结果。使用async管道不需要再执行 可观察对象的 订阅 或是 promise的then来获取数据了,async自动调用相应的方法获取数据。

AsyncPipe 订阅一个 Observable 或 Promise 对象,并返回它发出的最新值。 当发出新值时,异步管道会主动调用变化检测器的 markForCheck() 方法,标识组件需执行变化检测。 当组件被销毁时,异步管道自动取消订阅,以避免潜在的内存泄漏。

使用 ?. 安全导航操作符,控制 name 属性的显示:

<span>{{ (hero$ | async)?.name }}</span>

AsyncPipe with Promise

Promise 未使用 AsyncPipe

promise.component.ts

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

@Component({
    selector: 'exe-promise',
    template: `
     <h4>Promise Component</h4>
     <p>{{promiseData}}</p>
    `
})
export class PromiseComponent {
    promiseData: string;

    constructor() {
        this.getPromise().then(v => this.promiseData = v);
    }

    getPromise(): Promise<string> {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('Promise complete!');
            }, 2000);
        });
    }
}

app.component.ts

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

@Component({
  selector: 'exe-app',
  template: `
   <exe-promise></exe-promise>
  `
})
export class AppComponent { }

Promise 使用 AsyncPipe

promise-async-pipe.component.ts

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

@Component({
    selector: 'exe-promise-pipe',
    template: `
     <h4>Promise with AsyncPipeComponent</h4>
     <p>{{ promise | async }}</p>
    `
})
export class PromiseAsyncPipeComponent {
    promise: Promise<string>;
    constructor() {
       this.promise = this.getPromise();
    }

    getPromise(): Promise<string> {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('Promise with AsyncPipe complete!');
            }, 2000);
        });
    }
}

app.component.ts

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

@Component({
  selector: 'exe-app',
  template: `
   <exe-promise-pipe></exe-promise-pipe>
  `
})
export class AppComponent { }


AsyncPipe with Observables

Observable 未使用 AsyncPipe

observable.component.ts

import { Observable, Subscription } from 'rxjs/Rx';
import { Component, OnDestroy } from '@angular/core';

@Component({
    selector: 'exe-observable',
    template: `
     <h4>Observable Component</h4>
     <p>{{ observableData }}</p>
    `
})
export class ObservableComponent implements OnDestroy {
    observableData: number;
    subscription: Subscription = null;

    constructor() {
        this.subscribeObservable();
    }

    getObservable(): Observable<number> {
        return Observable
            .interval(1000) // 每隔1秒,生成一个值
            .take(10) // 获取前面10个数据
            .map(v => v * v); // 对每个数据进行乘方处理
    }

    subscribeObservable() {
        this.subscription = this.getObservable()
            .subscribe(v => this.observableData = v);
    }

    ngOnDestroy() { // 组件销毁时取消订阅,以避免潜在的内存泄漏
        if (this.subscription) {
            this.subscription.unsubscribe();
        }
    }
}

app.component.ts

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

@Component({
  selector: 'exe-app',
  template: `
   <exe-observable></exe-observable>
  `
})
export class AppComponent { }

Observable 使用 AsyncPipe

observable-async-pipe.component.ts

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Rx';

@Component({
    selector: 'exe-observable-pipe',
    template: `
     <h4>Observable with AsyncPipe Component</h4>
     <p>{{ observable | async }}</p>
    `
})
export class ObservableAsyncPipeComponent {
    observable: Observable<number>

    constructor() {
        this.observable = this.getObservable();
    }

    getObservable(): Observable<number> {
        return Observable
            .interval(1000)
            .take(10)
            .map(v => v * v);
    }
}

以上代码运行后能正常显示结果,但如果你切换到开发者工具的网络面板,你会发现发送了三个重复的请求。这是因为我们的 Observable 是 cold 的,每处使用 async 管道的地方都会执行一次。针对上述问题,大部分人推荐的解决方案如下:

this.http.get('https://jsonplaceholder.typicode.com/posts/1')
     .map(res => res.json()).share()
我们使用 publishReplay 替换了 share 操作符。调用 publishReplay() 方法后将返回一个ConnectableObservable 对象,
当你调用 connect()  方法的时候,将主动执行订阅操作。

在大多数情况下,我们只需要从服务器获取数据并显示数据。如果只是这样的话,我们可以使用 Promise 来修复 AsyncPipe 发送多次 HTTP 请求的问题:

this.person = this.http.get("https://jsonplaceholder.typicode.com/posts/1")
 .map(res => res.json()).toPromise()

原文链接:https://segmentfault.com/a/1190000008759314

 类似资料:

相关阅读

相关文章

相关问答