After upgrading my project from Angular 11 to 12, rxjs from 6.6.6 to 7.1.0 and Typescript from 3.9.7 to 4.0.2, I'm getting the following error related to my timer subscription:
material-input.component.ts:1262:7 - error TS2322: Type 'void' is not assignable to type 'Subscription'. 1262 this.onBlurTimerSubscription = timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY).subscribe(() => {
The timer is in the onBlur handler below:
onBlurTimerSubscription: Subscription;
// Below works to resolve the error. Is it ok?
// onBlurTimerSubscription: Subscription | any;
onBlur(event: any) {
this.allowOnChangeEvent = true;
this.cleanupUnmatchedError();
this.allowApiCalls = false;
this.hasFocus = false;
if (this.autoCompleteDisabled) {
this.onBlurComplete(event);
} else {
/**
* NOTE - Need to prioritize the `optionSelected` event over blur.
* Since the `onChange` event is debounced, if blur fires first
* theres a chance it won't execute properly.
*/
const ALLOW_PRIORITY_OPTION_SELECTED_DELAY = 10 this.debounceCustomEventDelay;
this.onBlurTimerSubscription = timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY).subscribe(() => {
this.onBlurComplete(event);
}).add(() => {
safeUnsubscribe(this.onBlurTimerSubscription);
});
}
}
This code has worked without issue prior to the updates mentioned above. What steps do I need to take to refactor for the error?
CodePudding user response:
You can solve this in different ways:
Create a private
class property of type Subscription
, store the subscription and in ngOnDestroy
life cycle hook, unsubscribe to it:
...
export class Component implements OnDestroy {
private mySub = new Subscription();
inSomeFunction() {
// like this or
this.mySub = timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY)
.subscribe(() => this.onBlurComplete(event))
// like this
// this works better if you want to handle multiple
// subscriptions, you just add them
this.mySub.add(
timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY)
.subscribe(() => this.onBlurComplete(event))
);
}
ngOnDestroy(): void {
this.mySub?.unsubscribe(); // don't forget the ? operator
}
}
Or you can managed the subscription with a Subject
:
...
export class Component implements OnDestroy {
private ngSubscription = new Subject();
inSomeFunction() {
timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY)
.pipe(takeUnitl(this.ngSubscription))
.subscribe(() => this.onBlurComplete(event))
}
ngOnDestroy(): void {
this.ngSubscription.next();
this.ngSubscription.complete();
}
}