Угловые, потребляющие наблюдаемые объекты с проблемами с объектами поведения

#angular #observable #angular-services #behaviorsubject

Вопрос:

Я создал беспорядок кода, пытаясь разобраться в том, как правильно использовать общие данные.

У меня есть служба, которая потребляет данные из других служб и возвращает вычисленный интерфейс. (IDriverProfile)

Проблема, с которой я сталкиваюсь, заключается в том, что я хочу потреблять все услуги сразу. Первоначально я использовал forkJoin для этого, и это отлично сработало. В тот момент, когда я попытался изменить данные, чтобы извлечь их из объекта поведения, как наблюдаемое, что-то сломалось.

Я совершенно уверен, что делаю что-то не так с combineLatest, но есть ли какой-то лучший способ подойти к этому? Это кажется довольно простым вариантом использования:

  1. Службы запросов для отфильтрованных данных
  2. Изменение данных на основе некоторого общего набора данных
  3. Объедините в расходуемый объект
  4. Компонент потребляет сервис DriverProfileService

Профиль водителя.Service.ts (Попытка 1)

Сбой из-за того, что соединение не завершается из объекта 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);
  }
 

Профиль водителя.Service.ts (попытка 2 combineLatest)

Not sure why this fails?

  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$;
  }
 

Статус.Сервис.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();
  }

 

Комментарии:

1. Я начал читать это, но остановился после того, как у меня разболелась голова. Это не так уж много кода, я предлагаю спланировать, чего вы хотите и как вам нужно его использовать, а затем переписать это. Совершенно непонятно, почему вы используете и комбинируете последние и разветвленные соединения и, по-видимому, дважды выполняете одни и те же вызовы API.

2. Я могу прояснить это, я просто пытался включить оба набора кода, которые я пробовал. Сначала я попробовал раздвоение, затем, во-вторых, я попытался комбинировать. И то, и другое не дает желаемых результатов. forkJoin не выполняется из-за объекта «Поведение». тест на комбинацию, похоже, тоже не работает?

Ответ №1:

getDriverProfile Метод, на который, как я предполагаю, подписывается в одном из ваших компонентов, когда вы упоминаете шаг 4: «Компонент использует DriverProfileService».

Профиль водителя.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
        } 
    });
  }
 

Что касается вашего Статуса.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);
}
 

Комментарии:

1. Спасибо, это привело меня туда, куда я направлялся. Ваше здоровье!