Reputation: 611
I'm using Subscription to get a parameter from the route in angular. Here is the code:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription} from 'rxjs';
@Component({
selector: 'farm-house',
templateUrl: './house.component.html',
styleUrls: ['./house.component.scss']
})
export class GreenhouseComponent implements OnInit, OnDestroy {
private routeSub: Subscription;
id: string;
constructor(private route: ActivatedRoute) {
this.id = "";
}
ngOnInit(): void {
this.routeSub = this.route.params.subscribe(params => {
this.id = params['id'];
});
}
ngOnDestroy() {
this.routeSub.unsubscribe();
}
}
But the problem is that the compiler says:
Property 'routeSub' has no initializer and is not definitely assigned in the constructor.
My question is, what is the best way to initialize a Subscription object?
Upvotes: 2
Views: 8216
Reputation: 3175
I just use:
private subscriptions: Subscription = new Subscription()
During your code, you can then use:
this.subscriptions.add()
And don't forget to unsubscribe:
ngOnDestroy() {
this.subscriptions.unsubscribe()
}
Upvotes: 0
Reputation: 400
Note that you can remove this error by adding "strictPropertyInitialization": false
in you tsconfig.json
{
"compilerOptions": {
"strictPropertyInitialization": false,
}
}
Then you don't need to do this proper initialization, or add a second type undefined
: private routeSub: Subscription | undefined
Upvotes: -1
Reputation: 624
Way 1:
Where I have a single subscription.
private routeSub?: Subscription;
ngOnInit(): void {
this.routeSub = this.route.params.subscribe(params => {
this.id = params['id'];
});
}
ngOnDestroy(): void {
// no need to do a separate if, use ? it is more readable
this.routeSub?.unsubscribe();
}
Way 2 where I have multiple subscriptions, I clean them all up with a single clean up:
private destroyed$ = new Subject<boolean>();
Somewhere() {
combineLatest([userService.spaceName$, userService.userName$])
.pipe(takeUntil(this.destroyed$))
.subscribe(([space, username]) => {do something...}
}
ngOnDestroy() {
this.destroyed$.next(true);
this.destroyed$.complete();
}
third way - mostly the best way
myObservable$: Observable<myInterface>;
ngOnInit() {
this.myObservable$ = this.myservice.someObservable$;
}
... html ...
<ng-container *ngIf='myObservable$ | async as list; else simpleInput'>
This last process works with onPush and you never forget to unsubscribe.
Note the first way is really handy when you subscribe and unsubscribe as part of the call, even combined with the second way:
pollUser(): void {
// if it has been hear before unsubcribe, otherwise skip it.
this.subscription?.unsubscribe();
this.subscription= this.someservice(serviceParameters)
.pipe(takeUntil(this.destroyed$))
.subscribe(result => {
this.useResult = result;
});
}
Upvotes: 0
Reputation: 161
Unsubscribe is not needed here because Angular destroys this particular subscription for you.
Upvotes: -1
Reputation: 611
I've come up with another solution which is using Subscription.EMPTY
from this question.
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription} from 'rxjs';
@Component({
selector: 'farm-house',
templateUrl: './house.component.html',
styleUrls: ['./house.component.scss']
})
export class GreenhouseComponent implements OnInit, OnDestroy {
private routeSub: Subscription;
id: string;
constructor(private route: ActivatedRoute) {
this.routeSub = Subscription.EMPTY;
this.id = "";
}
ngOnInit(): void {
this.routeSub = this.route.params.subscribe(params => {
this.id = params['id'];
});
}
ngOnDestroy(): void {
if(this.routeSub) {
this.routeSub.unsubscribe();
}
}
}
Upvotes: 8
Reputation: 5985
Should just be
private routeSub: Subscription = new Subscription
This is what worked for me.
Upvotes: 4
Reputation: 1
If you declare routeSub: any;
the compiler shouldn't complain.
source: saw it done in this post and i worked for me
Upvotes: -1
Reputation: 6016
Most of the cases it's should be enough to check the subscription before unsubscribe.
ngOnDestroy() {
if(this.routeSub) {
this.routeSub.unsubscribe();
}
}
In your case, it's not required to initialize subscription because you already called subscribe method in ngOnInit()
. Error might come because you are calling unsubscribe()
directly on Subscription without checking it's initialized or not.
Upvotes: 1