1

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: }
Marcell
  • 91
  • 9
  • if you comment these lines out does the error go away? is there a base class / are u using inheritance? have you tried wrapping these lines in an if block instead of using ?. operator? – danday74 Nov 01 '21 at 00:02
  • How is the subscribe written? – hozefam Nov 01 '21 at 06:01
  • @danday74 Yes, if the ngOnDestroy block is empty, there's no error. @hozefam It's written like `this.aSubscription$ = x$().subscribe()` – Marcell Nov 01 '21 at 08:33
  • I don't know much futher but if you inspect Subscription.add() function it gets the observables as TeardownLogic type, so even though you don't have anything like teardown it's embedded inside its logic. Probably you don't conveniently subscribe the services inside subscription functions. – Fatih Ersoy Nov 01 '21 at 08:45

2 Answers2

0

If you are suscribing like this

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

then in the ngOnDestroy() write

aSubscription_instance && aSubscription_instance.unsubscribe()
hozefam
  • 980
  • 1
  • 7
  • 13
0

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 ...

danday74
  • 52,471
  • 49
  • 232
  • 283
  • This approach seems like working, although I'm a bit sceptical about it, so will do some experimentation and get back to you later. By the way, why do I need to call `next()` before `complete()`? – Marcell Nov 01 '21 at 10:18
  • I've got no idea - this is just how the pros do it, its documented on many articles on the Internet, just search it up - I've been using this approach for years without issue – danday74 Nov 01 '21 at 10:27