асинхронный канал внутри ngIf все еще получает значение

Я хочу написать складной компонент с кнопкой «Развернуть», открывающей список элементов. Этот список создается с помощью веб-запроса, и мне интересно, когда этот запрос произойдет - поскольку, насколько я понимаю, канал async похож на подписку, а ngIf приведет к воссозданию компонента, подписывающегося на подписку, я бы ожидал, что значение запроса быть доступным только один раз, однако он создается каждый раз, когда я «показываю» расширитель.

минимальный пример StackBlitz

Внутри моего AppComponent есть такая логика:

  data$ = of('expensive data from server').pipe(
    take(1),
    tap(() => console.log('data from server emit!')),
    // shareReplay(1),
    finalize(() => console.log('complete!'))
  );
  showSon = true;

Шаблон такой:

<button (click)="showSon=!showSon">Click me!</button>
<p *ngIf="showSon">
  <ng-container *ngIf="data$ | async as data">
    <div>{{data}}</div>
  </ng-container>
</p>

Насколько я понимаю, поскольку наблюдаемое создается через of, оно должно запускать свое значение один раз, а затем завершать, подтвержденное журналами консоли. Однако я удивлен, что каждый раз, когда я показываю элемент внутри ngIf, я все равно получаю значение, хотя теперь async подписывается на завершенный наблюдаемый объект, который не является ReplaySubject.

Я думаю, что использование shareReplay(1) решит проблему создания нескольких веб-запросов, но я до сих пор не понимаю, как одноразовый наблюдаемый объект постоянно доступен всякий раз, когда шаблон внутри ngIf воссоздается.


person Ran Lottem    schedule 03.10.2020    source источник
comment
Каждый раз, когда If истинно, элемент воссоздается ... поэтому асинхронный канал повторно подписывается на наблюдаемые данные $, вызывая его повторное излучение ..   -  person MikeOne    schedule 03.10.2020


Ответы (1)


Комментарий MikeOne правильный. Everytime the If is true, the element gets recreated.. so the async pipe re-subscribes to the data$ observable causing it to emit again..

Ваше решение также правильное, чтобы использовать shareReplay(1), как вы упомянули .

person Robert Dempsey    schedule 03.10.2020