简体   繁体   中英

async pipe inside ngIf still gets value

I want to write a collapsible component which has an "Expand" button that opens a list of items. This list is created through a web request, and I'm wondering when this request happens - since to my understanding the async pipe is like a subscription and the ngIf would cause the component subscribing to be recreated, I would expect the value of the request to only be available once, however it is created each time I 'show' the expander.

StackBlitz minimal example

Inside my AppComponent I have this logic:

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

The template is like this:

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

My understanding is that since the observable is created via of , that it should fire its value once and then complete, confirmed by the console logs. However I'm surprised that every time I show the element inside the ngIf , I still get a value even though async is now subscribing to a completed observable that is not a ReplaySubject .

I think using shareReplay(1) would solve the issue of making multiple web requests, but I still don't understand how the single-use observable is repeatedly available whenever the template inside the ngIf is recreated.

MikeOne's comment is correct. Everytime the If is true, the element gets recreated.. so the async pipe re-subscribes to the data$ observable causing it to emit again..

Your solution is also correct, to use shareReplay(1) as you've mentioned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM