Reputation: 3587
I have a service that returns an Observable:
contactsSerice (): Observable<Contact[]> {...}
For using this data on my template and keep the template "alive" based on what's in the Observable I've found two ways.
I declared a Subject
within the context of my Component:
export class ExampleComponent implements OnInit {
contacts$: Subject<Contact[]> = new Subject<Contact[]>();
constructor(){}
}
And then:
ngOnInit() {
this.contactsSerice().subscribe((contacts: Contact[]) => {
this.contacts$.next(contacts);
});
}
.subscribe()
using my Subject as a parameter:ngOnInit() {
this.contactsSerice().subscribe(this.contacts$);
}
After this, I can use the | async
pipe in the template like:
<section *ngIf="contacts$ | async as contacts">
...
</section>
I was wondering if there's any practical difference between calling subscribe()
passing the Subject vs properly subscribing to the Observable and trigger the Subject's next()
method.
Upvotes: 2
Views: 508
Reputation: 1783
There is an actual difference:
When we are subscribing via a Subject
then error
and complete
notifications are passed to it. So if our source observable is completing, then the subject is completing as well. This might be an unwanted behaviour, because a completed Subject
does ignore all further notifications.
/*
Variant 1:
This works only once:
- The complete notification from the HTTP call is forwarded to the subscribing subject
- A completed subject ignores further values
*/
this.inventoryService.loadBeers(page).subscribe(this.beers$);
// could be thought of the same as:
this.inventoryService.loadBeers()
.subscribe(
(response) => this.beers$.next(response),
(error) => this.beers$.error(error),
() => this.beers$.complete()
);
/*
Variant 2: Here we don't pass the completed event to the beers$
*/
this.inventoryService.loadBeers()
.subscribe(
(response) => this.beers$.next(response),
(error) => console.log('Errors are not passed to beers$ subject'),
() => console.log('Complete notification is not passed to beers$ subject')
);
You can also take a look at the stackblitz example where I tried to show this behaviour.
Upvotes: 3
Reputation: 3588
The short answers is none, there is no difference (besides that you will be using a bit more memory for the Subject itself).
From a practical point of view (let's say the question is when should I use intermediate Subject) you want to use intermediate subjects whenever you want to cache somehow the response that you receive from your back-end.
Let's say for example you want to do the following thing
// Left side of the screen
<section *ngIf="contacts$ | async as contacts">
...
</section>
// Right side of the screen
<section *ngIf="contacts$ | async as contacts">
...
</section>
So in this case, if you are using directly the service you will make two calls to the back-end (as each |async
is a new subscription).
So the short answer is that there will be no difference, but it is better to have it.
** Side note: If you are new to Angular and have trouble managing states, look into NGRX.
Upvotes: -1