Using Angular I have a service to share some variable from different components. Like this:
import { Injectable } from "@angular/core";
import { BehaviorSubject } from "rxjs";
@Injectable()
@Injectable({
providedIn: "root"
})
/**
* Service to manage all the global variables in order to use it in different components
*/
export class SharedService {
// Global variable of the path
private rPathSource = new BehaviorSubject(""); // Set up the source
currentRPath = this.rPathSource.asObservable(); // Make it Observable
constructor() {}
/**
* Function to change the global path from a component
* @param path string of the path of the R Folder for the result of the ML
*/
changeRPath(path: any) {
this.rPathSource.next(path);
}
}
Then from a component I subscribe to it. Like this: Component 1
constructor(private shared: SharedService) {}
ngOnInit() {
this.shared.currentRPath.subscribe(RPath => {
this.currentRPath = RPath;
// HERE I DO A GET REQUEST
});
}
And from another component I change the variable like this: Component 2
this.shared.changeRPath("");
I have a sidenav bar with some buttons and each button change the url and the component loaded with ng content.
<ng-content></ng-content>
When I press the button to redirect on the component 1 I susbcribe to the variable and the get request is done. Everything is fine.
The problem is when I press the button to redirect on the component 2 the shared variable changes and because I susbcribe on the component 1 it does the get request again. Indeed, the get request is in the callback of the subscribe.
But what is weird is that the component 1 is not load anymore because it is the component 2. It is not supposed to be destroyed when the component changes ?
You must not forget to unsubscribe to avoid memory leaks in these dangling subscriptions.
Here are 2 ways to do that:
Use takeUntil
:
export class MyComponent implements OnDestroy, OnInit {
private readonly destroyed = new Subject<void>();
constructor(private readonly shared: SharedService) {}
ngOnInit() {
this.shared.currentRPath.pipe(takeUntil(this.destroyed)).subscribe(/*...*/);
}
ngOnDestroy() {
this.destroyed.next(undefined);
this.destroyed.complete();
}
}
Unsubscribe (useful when you have a single subscription):
const mySubscription = this.shared.currentRPath.subscribe(/*...*/);
mySubscription.unsubscribe(); // when done.