Angular,使用具有 BehaviorSubject 问题的 Observables

Angular, consuming Observables with BehaviorSubject issues

我创建了一堆代码,试图找出正确使用共享数据的实际方法。

我有一个服务正在使用来自其他服务的数据,并返回一个计算接口。 (IDriverProfile)

我面临的挑战是我想一次使用所有服务。我最初为此使用了 forkJoin,效果很好。当我尝试将数据更改为从 BehaviorSubject 中提取作为 Observable 的那一刻,事情就坏了。

我很确定我在 combineLatest 上做错了什么,但是有更好的方法来解决这个问题吗?这似乎是一个相当基本的用例:

  1. 筛选数据的查询服务
  2. 根据一些共享数据集改变数据
  3. 合成消耗品
  4. 组件使用 DriverProfileService

DriverProfile.Service.ts(尝试 1)

由于 forkJoin 未从 behaviorSubject 完成而失败。

 getDriverProfile(data:IDriverData): Observable<IDriverProfile>{
    let driverStandings:IDriverStanding[] = [];
    let driverQualifying:IQualifying[] = [];
    let driverResults:IResult[] = [];
    let careerStats:IDriverCareerStats;   
    let SeasonData:IDriverSeasonData[]=[];
    
    let profile:IDriverProfile = {
      driverData: data,
      seasonsData: SeasonData,
      careerStats: careerStats
    };    

  // start forkJoin (works if all observables not utilizing shared data)  
    forkJoin({
      QualyTask: this.qualifyService.getDriverQualifyingLaps(data.driver),
      StandingsTask: this.driverStandingsService.getDriverStandings(data.driver),
      ResultsTask: this.resultService.getDriverResults(data.driver),
      RaceTask: this.raceService.getAllRaces(),
      statusTask: this.statusService.status$,
      teamsTask: this.teamsService.getAllConstructors()
    }).subscribe(({QualyTask, StandingsTask, ResultsTask, RaceTask, statusTask, teamsTask})=>{
      driverQualifying = QualyTask;      
      driverStandings = StandingsTask;
      driverResults = ResultsTask;    
      let races = RaceTask; 
      let allStatus = statusTask;
      let teams = teamsTask;
      console.log('all status',allStatus);

      let results = this.getResults(driverResults, races, driverStandings, allStatus, teams);
      //console.log("results", results);
      // calc career stats
      profile.seasonsData = results.seasons;
      profile.careerStats = results.stats;
    });    
    console.log("profile", profile);
    

    return of(profile);
  }

DriverProfile.Service.ts(尝试 2 CombineLatest)

不确定为什么会失败?

 getDriverProfile(data:IDriverData): Observable<IDriverProfile>{
    
// this section is for trying combineLatest (broken)
    let task1 = this.qualifyService.getDriverQualifyingLaps(data.driver);
    let task2 = this.driverStandingsService.getDriverStandings(data.driver);
    let task3 = this.resultService.getDriverResults(data.driver);
    let task4 = this.raceService.getAllRaces();
    let task5 = this.statusService.status$;
    let task6 = this.teamsService.getAllConstructors();
    const combine$ = combineLatest(task1, task2, task3, task4, task5, task6,
      (t1,t2,t3,t4,t5,t6)=> {
        let results = this.getResults(t3, t4, t2, t5, t6);
        return <IDriverProfile> {
          driverData: data,
          seasonsData: results.seasons,
          careerStats: results.stats
        }
      });  

    return combine$;
  }

Status.Service.ts

private readonly _StatusSource = new BehaviorSubject<IStatus[]>([]);

  readonly status$ = this._StatusSource.asObservable();

  constructor(private httpClient:HttpClient) { 
    this.loadInitialData();
  }

  loadInitialData() {
    this.httpClient.get<IStatus[]>("assets/data/status.json").subscribe(x => {
      //console.log('status load', x);
      this._setStatus(x);
    },
    err => console.log("Error loading Status")
    );
  }

  getStatus(): IStatus[] {
    return this._StatusSource.getValue();
  }

  private _setStatus(status: IStatus[]): void {
    this._StatusSource.next(status);
    this._StatusSource.complete();
  }

正如您提到的第 4 步:“组件消耗 DriverProfileService”。

我假设正在您的一个组件中订阅该方法

DriverProfile.Service.ts 更新方法如下:

// Assuming everything within the combine latest call are observables. 

 getDriverProfile(data:IDriverData): Observable<IDriverProfile> {
    return Observable.combineLatest(
        this.qualifyService.getDriverQualifyingLaps(data.driver),
        this.driverStandingsService.getDriverStandings(data.driver),
        this.resultService.getDriverResults(data.driver),
        this.raceService.getAllRaces(),
        this.statusService.getStatusSource(),
        this.teamsService.getAllConstructors()
    ).map((t1,t2,t3,t4,t5,t6) => {

        // I assume getResults is not an observable, it just transforms data or something.
        let results = this.getResults(t3, t4, t2, t5, t6);

        return <IDriverProfile> {
          driverData: data,
          seasonsData: results.seasons,
          careerStats: results.stats
        } 
    });
  }

至于你的Status.Service.ts让我们保持简单:

// Declare your subject and set value to empty array
private statusSource = new BehaviorSubject<IStatus[]>([]);

// Contructor calling the method to get data initially
constructor(private httpClient:HttpClient) { 
    this.loadInitialData();
}

loadInitialData() {
    this.httpClient.get<IStatus[]>("assets/data/status.json")
    .subscribe(statusSource => {
        this.setStatusSource(statusSource);
    },(error) => console.log(error));
}

// Gets the status source
getStatusSource(): Observable<IStatus[]> {
    return this.statusSource.asObservable();
}

// Sets the status source
public setStatusSource(statusSource: IStatus[]): void {
    this.statusSource.next(statusSource);
}