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();
}
}
