У меня есть следующие две подписки:

this.service1.source1.subscribe(countries => {
  this.filteredData =  [];
  countries.forEach(country => {
    this.filteredData = this.data.filter(user => {
      return user.country == country;
    });
  });
});

this.service2.source2.subscribe(companies => {
  companies.forEach(company => {
    this.filteredData =  [];
    this.filteredData = this.data.filter(user => {
      return user.company == company;
    });
  });
});

Где source1 и source2 - BehaviorSubject, и оба события перехватываются subscribe.

Я хочу объединить обе подписки, потому что я хочу фильтровать данные в зависимости от обоих результатов, возвращаемых subscribe

Я пытался forkJoin и zip

zip([this.service1.source1, this.service1.source2]).subscribe(results => {
  console.log('zip results:', results);
});

forkJoin([this.service1.source1, this.service1.source2]).subscribe(results => {
  console.log('forkJoin results:', results);
});

Но с этими (zip и forkJoin) я заметил, что я даже ничего не получаю на консоли, как будто subscribe не запускается, когда генерируются события.

Как объединить результаты обоих источников в одну подписку?

1
chris 19 Июн 2019 в 17:18

3 ответа

Лучший ответ

forkJoin может не подходить для вашего варианта использования, поскольку он испускает последнее излученное значение из каждого, когда все наблюдаемые ЗАВЕРШЕНЫ.

zip также может не дать вам желаемого поведения, потому что ожидает, чтобы все входные потоки испустили все свои n-ые значения, и как только это условие выполнено, оно объединяет все эти n-ые значения и выдает n-е объединенное значение.

Так что в любом случае вы не получите излучение, пока в обеих наблюдаемых не будет излучения. поскольку this.service1.source1 и this.service1.source2 являются BehaviorSubject использование zip гарантирует начальную эмиссию. но более поздние выбросы будут происходить только тогда, когда будут наблюдаться обе наблюдаемые.

Я предлагаю использовать Зернокомбинацию beacuse всякий раз, когда издается какой-либо поток ввода значение, оно объединяет последние значения, испускаемые каждым входным потоком.

combineLatest(this.service1.source1, this.service1.source2).subscribe(results => {
  console.log('combineLatest results:', results);
});

И поскольку this.service1.source1 и this.service1.source2 являются BehaviorSubject такой что:

Вариант Subject, который требует начального значения и выдает свое текущее значение всякий раз, когда он подписан.

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

2
ysf 19 Июн 2019 в 15:06

Синтаксис неверен. Оба forkJoin и zip принимают наблюдаемые в качестве аргументов. НЕ массив наблюдаемых. Удалите [] из звонка, и все будет в порядке.

Попробуй это:

zip(this.service1.source1, this.service1.source2).subscribe(results => {
  console.log('zip results:', results);
});

forkJoin(this.service1.source1, this.service1.source2).subscribe(results => {
  console.log('forkJoin results:', results);
});
1
SiddAjmera 19 Июн 2019 в 14:21

Как указывалось выше @ysf, если вы хотите отфильтровать локальные данные с обоими результатами при любом из выбросов, вам следует выбрать combineLatest.

Кроме того, я рекомендую вам создать переменную в каждом сервисе в качестве наблюдаемого экземпляра для BehaviorSubject. Подобно:

// at Service1.service.ts
export class Service1Service {
  // Do not expose Subject directly.
  private source1 = new BehaviorSubject<YourDataType[]>(YourInitialValue);
  private source2 = new BehaviorSubject<YourDataType[]>(YourInitialValue);

  source1$: Observable<YourDataType[]>;
  source2$: Observable<YourDataType[]>;

  constructor() {
    // Create an Observable instance for your sake and open it to the public.
    this.source1$ = this.source1.asObservable();
    this.source2$ = this.source2.asObservable();
  }
}


// at wherever you subscribe
combineLatest(this.service1.source1$, this.service1.source2$).pipe(
  filter(([res1, res2]: YourDataType[]) => {
    // Filter your data with res1, res2
  })
).subscribe();
1
DongBin Kim 20 Июн 2019 в 09:44