In Angular every time a endpoint needs to be queried, this code needs to be called:
this.service.getSomeData()
.pipe(takeUntil(this.onDestroy$))
.subscribe((message: any) => {
some code here;
}
takeUntil is a function in a component to unsubscribe when component is destroyed.
How to refactor the code above so it wont be needed to type all of this every time a resource is used? So it looks like this at the end (more or less?):
this.service.getSomeData(
(message: any) => {
some code here;
}
)
One option is to use the async pipe in your template to manage the subscriptions
data$ = this.service.getSomeData();
and in your template
<ng-container *ngIf="data$ | async as data">
{{ data | json }}
You can use the template variable data here that magically updates every time data$
emits and no need to unsubscribe as the async pipe manages the subscription for you
</ng-container>
If the observable emits data that is not in the shape you need for your template then use a map function
data$ = this.service.getSomeData().pipe(map(data => functionThatTransformsData(data)));
You can have a read of the pattern I use with my state management library here https://medium.com/@adrianbrand/angular-state-management-with-rxcache-468a865fc3fb
Generally your services don't have to be destroyed/disabled after some component is unmounted from view/dom. Treat them like a layer of code to perform some data transformation or fetching.
Q: Why does everyone use takeUntil(this.destroyed$)
or this.subscription.unsubscribe()
?
A: The Observable
lives as long as there is at least one subscriber for it. So if you have some long-living observables that are not completed immediately after some action, you will have memory leaks (Angular can create/initialize each component multiple times). Speaking of Angular
's http
, all of get
, post
, put
and delete
calls are completed after the backend call is done. This means that you don't have to add unsubscribe
in onDestroy
hook or use takeUntil
.
If you have established a Websocket
connection and are listening to some messages, your stream become long-lasting and each component that is subscribed to this messaged should unsubscribe during onDestroy
cycle. If you don't do this, Angular can initialize your component multiple times (this usually happens with *ngIf=""
statements) and multiple subscriptions are created but never destroyed. This leads to memory leaks.
Unfortunately this is a common problem for most of the Angular projects that can be solved by either manual unsubscribe
/ takeUntil
or by using the async
pipe that automatically performs unsubscribe
after the component is destroyed.
I am glad you asked that, I came across this Angular AutoUnsubscribe (I am referencing this because I found that the logic to implement this is really beautiful.)
Its relatively easy to use, and workes across all declarables(pipes, directives, and components obviously.)
Now to omit both the subscribing and unsubscribing part (that I won't suggest), it pretty simple, and straight forward.
Earlier you had something like
getSomeData(): Observable<any> {
// for eg
return this.http.get();
}
You have to Change it to:
getSomeData(callback, onDestroy$): Observable<any> {
this.http.get(...).pipe(takeUntil(onDestroy$)).subscribe(val => callback(val));
}
Then we'll be able to have what we finally wanted. Cheers.
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.