Reputation:
I'm here thinking about observables ..
And I imagined the following situations:
Example 1)
In my case when I use NGRX
I create all the architecture correctly, and I create a selector service for that particular store.
In the service it is not possible to use ngOnDestroy because it is not a component and I have the following question, is there a memory leak in a service? Or does this service automatically destroy observables?
Example 2) Using the selectors in example one, is it necessary to subscribe to this selector and then destroy it?
PEOPLE-SELECTORS.SERVICE
@Injectable({ providedIn: 'root' })
export class PeopleSelectorsService {
constructor(private readonly store: Store<StoreState>) {}
get error(): Observable<IRequestError> {
return this.store.pipe(select(fromPeopleSelectors.getError));
}
get loading(): Observable<boolean> {
return this.store.pipe(select(fromPeopleSelectors.getLoading));
}
get main(): Observable<IPeople> {
return this.store.pipe(select(fromPeopleSelectors.getMain));
}
get total(): Observable<number> {
return this.store.pipe(select(fromPeopleSelectors.selectTotal));
}
get all(): Observable<Array<IPeople>> {
return this.store.pipe(select(fromPeopleSelectors.selectAll));
}
get allIds(): Observable<Array<string | number>> {
return this.store.pipe(select(fromPeopleSelectors.selectIds));
}
}
APP.COMPONENT
ngOnInit(): void {
this.peopleDispatchService.getAll();
this.isLoading$ = this.peopleSelectorsService.loading;
}
<main [attr.isLoading]="isLoading$ | async">
<ng-container></ng-container>
<app-loading-container *ngIf="isLoading$ | async; else isMainController"></app-loading-container>
<ng-template #isMainController>
<app-user-talk-controller-container></app-user-talk-controller-container>
<app-user-talk-container></app-user-talk-container>
</ng-template>
</main>
Upvotes: 0
Views: 192
Reputation: 2379
is there a memory leak in a service? Or does this service automatically destroy observables?
The concept of destroying observables doesn't really make sense. You destroy subscriptions (by unsubscribing), not observables. So no, there's no need to "destroy" the observables in your service.
To your second point, no. The async pipe automatically unsubscribes when the component is destroyed. So as long as you use async
in the html template, you don't need to worry about subscribing and unsubscribing
Upvotes: 1
Reputation: 13584
That's totally normal.
Until you have a subscription you don't have any memory leaks.
async
pipe knows when to subscribe and when to unsubscribe so you shouldn't worry about forgotten subscriptions, async
will unsubscribe once the subscription isn't need anymore.
The best way is to write code full of pipes without any subscription IMHO.
For example in your case I would create a single observable in the app.component.ts that combines all data together and has a single observable.
ngOnInit(): void {
this.data$ = combineLatest(
this.peopleSelectorsService.loading,
this.peopleSelectorsService.all,
).map(([isLoading, records]) => ({isLoading, records}));
}
<ng-container *ngIf="data$ | async as data">
<main [attr.isLoading]="data.isLoading">
<ng-container></ng-container>
<app-loading-container *ngIf="data.isLoading; else isMainController"></app-loading-container>
<ng-template #isMainController>
<app-user-talk-controller-container></app-user-talk-controller-container>
<app-user-talk-container [records]="data.records"></app-user-talk-container>
</ng-template>
</main>
</ng-container>
the main benefit I see is that we have single subscription and there's no problem of subscription intersection, because time to time in template when you have several nested async
you can find that they can depend on each other too and they won't work properly. with a single subscription there's no such a problem.
Also that's what we do in our current project. time to time data$
is quite big, but still it feels better then several subscriptions in a template or in a class.
Upvotes: 1