Angular中利用rxjs庫的Subject多播解決在第一次訂閱時進行初始化操作(如第一次訂閱時從服務器獲取數據)


 

 

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

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM