Home > database >  Angular 12: TypeError: teardown.unsubscribe is not a function
Angular 12: TypeError: teardown.unsubscribe is not a function

Time:11-02

After upgrading my app to Angular 12, I'm getting this strange error message whenever I navigate away from a component of which the ngOnDestroy function contains .unsubscribe() calls. Even more strange, that teardown.unsubscribe isn't mentioned in my project whatsoever, making debugging very difficult.

ERROR Error: Uncaught (in promise): UnsubscriptionError: 1 errors occurred during unsubscription:
    1) TypeError: teardown.unsubscribe is not a function
Error
    at _super (createErrorClass.js:4)
    at new UnsubscriptionErrorImpl (UnsubscriptionError.js:3)
    at SafeSubscriber.unsubscribe (Subscription.js:55)
    at SafeSubscriber.unsubscribe (Subscriber.js:55)
    at FooComponent.ngOnDestroy (my-foo.component.ts:58)
    at executeOnDestroys (core.js:7406)
    at cleanUpView (core.js:7309)
    at destroyViewTree (core.js:7142)
    at destroyLView (core.js:7287)
    at RootViewRef.destroy (core.js:22651)
    at resolvePromise (zone.js:1213)
    at resolvePromise (zone.js:1167)
    at zone.js:1279
    at ZoneDelegate.invokeTask (zone.js:406)
    at Object.onInvokeTask (core.js:28667)
    at ZoneDelegate.invokeTask (zone.js:405)
    at Zone.runTask (zone.js:178)
    at drainMicroTaskQueue (zone.js:582)
    at ZoneTask.invokeTask [as invoke] (zone.js:491)
    at invokeTask (zone.js:1600)

my-foo.component.ts

57: ngOnDestroy(): void {
58:     this.aSubscription$?.unsubscribe();
59:     this.bSubscription$?.unsubscribe();
60:     this.cSubscription$?.unsubscribe();
61:     this.dSubscription$?.unsubscribe();
62: }

CodePudding user response:

If you are suscribing like this

 aSubscription_instance = this.aSubscription$.subscribe(() => {
      /// Code here
    });

then in the ngOnDestroy() write

aSubscription_instance && aSubscription_instance.unsubscribe()

CodePudding user response:

I really recommend the following pattern on subscriptions:

export class AComponent{
   subscriptions = new Subscription();

   //subscribing
   ngOnInit(){
    this.subscriptions.add(
      this.aService.subscribe(...)
    );
    this.subscriptions.add(
      this.bService.subscribe(...)
    )
   }

   //unsubscribing
   ngOnDestroy(){
    subscriptions.unsubscribe();
   }
}

This way you won't get errors, because rcjs Subscriptions are unsubscribed safely, you won't get errors even though no subscriptions are present.

CodePudding user response:

TBH none of these patterns are good. This is the best approach:

private unsubscribe$: Subject<any> = new Subject()

ngOnInit() {
  this.myService.pipe(takeUntil(this.unsubscribe$)).subscribe()
}

ngOnDestroy() {
  this.unsubscribe$.next()
  this.unsubscribe$.complete()
}

NOTE: .pipe(takeUntil(this.unsubscribe$)) does the unsubscribe - just add this for every sub - less boiler plate code. Use this approach and your problems will vanish away ...

  • Related