Angular2 + асинхронный канал: получение нескольких значений из одного Observale

У меня есть одна служба, которая возвращает один Observable. Теперь я ищу правильный/самый эффективный способ получить несколько результатов от этого Observable без написания слишком большого количества кода.

  • MyService возвращает Observable<Array<Foo>>

  • MyComponent вызывает myService.getFoos() и должен вывести первые 5 элементов из массива, а также общую длину массива и количество не показанных элементов.

Вот мой текущий код:

@Injectable()
export class MyService {
  foos = new BehaviorSubject<Array<Foo>>([]);

  getFoos() {
    return this.foos.asObservable();
  }
}



@Component({
  template: `
    Total: {{ totalCount | async }}
    Omitted: {{ (totalCount | async) - (maxFiveItems | async).length }}
    <div *ngFor="let item of maxFiveItems | async">
      {{item.bar}}
    </div>
  `
})
export class MyComponent {
  totalCount: Observable<number>;
  maxFiveItems: Observable<Array<Foo>>;

  constructor(myService:MyService) {
    this.totalCount = myService.getFoos()
        .map(arr => arr.length);

    this.maxFiveItems = myService.getFoos()
        .map(arr => arr.slice(0, 5));
  }
}

Результат выглядит нормально, но я использую канал async 4 раза. Что (насколько мне известно) приведет к 4 подпискам. Это вообще не должно быть необходимо, я думаю (?)


Конечно, я мог бы вручную подписаться на constructor из MyComponent и жить без async каналов. Но тогда я должен сам позаботиться об отписке.

Есть ли другой способ справиться с этим?


person Benjamin M    schedule 16.01.2017    source источник


Ответы (1)


Нет ничего плохого в том, что вы делаете, предполагая, что myService.getFoos() где-то внутри использует оператор share(), поэтому все ваши каналы async имеют одну и ту же подписку на источник. Если вы используете BehaviorSubject, как в этом примере, все в порядке.

То, что вы упомянули о подписке на себя в конструкторе, это то, что сразу пришло мне в голову. Хотя я не вижу проблемы в ручной отписке.

person martin    schedule 16.01.2017
comment
Я не понимаю, почему вы должны использовать share на BehaviorSubject. Что касается отказа от подписки, если вы вручную подписываетесь на что-то, что может выдавать более одного значения (это относится к поведенческому субъекту), вам необходимо отказаться от подписки. В противном случае вы получите утечку памяти. По сути, вы бы реализовали интерфейс OnDestroy в своем компоненте. - person Melou; 17.01.2017
comment
Помимо этого, я согласен с вами: подход @Benjamin кажется совершенно хорошим. - person Melou; 17.01.2017
comment
Я только что прочитал о предстоящей функции в Angular 4: ngIf с асинхронным конвейером и let (см.: netbasal.com/a-taste-from-angular-version-4-50be1c4f3550 ). Это может решить некоторые из этих сценариев с несколькими подписками. - person Benjamin M; 18.01.2017
comment
Да, новый ngIf был бы, вероятно, самым простым способом сделать это. - person martin; 19.01.2017