rxjs 庫中 Subject 類可以用於實現多播,其本身已經有多個實現(可參考【Rxjs】 - 解析四種主題Subject),但是都是需要手動操作Subject對象進行發布。
這里通過繼承 BehaviorSubject(Subject的實現類,也可以直接繼承Subject,但這里考慮到可能會用到初始值的時候)實現在第一次訂閱(調用subscribe方法)時進行初始化(可以從服務器獲取數據)。
第一步: InitSubject 類定義
import {BehaviorSubject, Subscriber, Subscription} from 'rxjs'; /** * 第一次訂閱時執行初始化操作. */ export class InitSubject<T> extends BehaviorSubject<T> { /** * 是否為第一次 */ private first = true; constructor(initValue: T, private init: () => void = () => {}) { super(initValue); } /** @deprecated This is an internal implementation detail, do not use. */ _subscribe(subscriber: Subscriber<T>): Subscription { if (this.first) { this.first = false; if (typeof this.init === 'function') { this.init(); } } return super._subscribe(subscriber); } }
第二步: Service中定義可觀察對象
import {Injectable} from '@angular/core'; import {InitSubject} from '../InitSubject'; import {HttpClient} from '@angular/common/http'; import {retry} from 'rxjs/operators'; /** * 獲取配置系統管理的應用列表等. */ @Injectable({ providedIn: 'root' }) export class AppService { /** * 用於發布信息,這里構造方法第二個參數傳入自定義初始化邏輯. */ public app$ = new InitSubject<Array<InternalApp>>(null, () => { this.http.get<any>('/get_xxx').pipe(retry(3)) .subscribe(value => this.app$.next(value.data)); }); constructor(private http: HttpClient) {} }
第三步: Service中定義可觀察對象
import {Component, OnDestroy, OnInit} from '@angular/core'; import {AppService} from '../../service/app.service'; import {Subscription} from 'rxjs'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.less'] }) export class HomeComponent implements OnInit, OnDestroy { // 應用信息 app: Array<any>; // 應用信息變更監聽 appSubscription: Subscription; constructor(private appService: AppService) { } ngOnInit(): void { // 初始化時定義訂閱並監聽數據變化 this.appSubscription = this.appService.app$.subscribe(value => this.app = value); } ngOnDestroy(): void { // 銷毀時取消訂閱,防止內存泄露 this.appSubscription.unsubscribe(); } }