Подписывайтесь на Тему только после получения данных от forkJoin

Я хочу передать некоторые данные из одного модуля в другой модуль. Для этого я использую Тему. Я создал тему ниже:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SelectedClusterService {

  constructor() { }

  public selectedClusterName = new Subject<string>();

}

Я передаю некоторые данные из «oneComponent» через вышеуказанную службу и перенаправляюсь на «anotherComponent»:

this.selectedClusterService.selectedClusterName.next(cluster_name);

И получение данных в «otherComponent» следующим образом:

this.selectedClusterService.selectedClusterName.subscribe(res => {
  this.selectedCluster = res;
  console.info("this.selectedCluster", this.selectedCluster);
});

Это работает нормально, я получаю данные в «другой компонент». Но в «otherComponent» я использую forkJoin. Я хочу получить данные от субъекта только после получения данных от forkJoin. Я пытаюсь так:

   ngOnInit() {
    forkJoin([
      this.dataService.getUpgradeAppList(),
      this.dataService.getClusterList()
    ]).subscribe((data: any) => {
      console.info("forkJoin :: ngOnInit ::", data);
      this.appList = data[0].apps;
      this.clusterList = data[1];

    }); 
    this.selectedClusterService.selectedClusterName.subscribe(res => {
      this.selectedCluster = res;
      console.info("this.selectedCluster", this.selectedCluster);
    });
  }

Я пробовал ngAfterViewInit, ngAfterContentChecked с помощью ChangeDetection, а также пытаюсь использовать setTimeout, но ничего не получается. Всегда сначала я получаю данные субъекта, а затем данные forkJoin. Как я могу сначала получить forkJoin, а затем данные субъекта? Любая помощь приветствуется...

Попробуйте использовать joinLatest вместо forkJoin.

Evgeny Gurevich 20.02.2024 13:06

@EvgenyGurevich тот же результат после использования mergeLatest

rk01 20.02.2024 13:14
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
2
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прежде всего, невозможно гарантировать последовательность получения данных в вашем компоненте при работе с асинхронными сущностями. Я бы использовал BehaviorSubject вместо Subject, чтобы гарантировать получение данных от другого компонента.

Ваш сервис будет таким:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SelectedClusterService {

  constructor() { }

  public readonly selectedClusterName = new BehaviorSubject<string | undefined>(undefined);

}

Ваш компонент:

ngOnInit() {
    forkJoin([
      this.dataService.getUpgradeAppList(),
      this.dataService.getClusterList()
    ]).
    pipe(
      tap((data: any) => {
        console.info("forkJoin :: ngOnInit ::", data);
        this.appList = data[0].apps;
        this.clusterList = data[1];
      }),
      switchMap(() => this.selectedClusterService.selectedClusterName),
      filter(res => res !== undefined)
    ).subscribe(res => {
      this.selectedCluster = res;
      console.info("this.selectedCluster", this.selectedCluster);
    });     
  }

В вашем anotherComponent вы можете использовать оператор switchMap, чтобы начать получать данные из oneComponent, и filter, чтобы игнорировать начальное значение в BehaviorSubject, которое мы установили в undefined.

Большое спасибо.. Работает, как и ожидалось. Я попробовал одно решение, которое применяет setTimeout при отправке данных из «oneComponent», и оно тоже работает. Но ваше решение намного лучше моего.

rk01 21.02.2024 06:48

Другие вопросы по теме