4

I have a component which does some service calls, and gets promises. After Promises are resolved I am doing detectChanges. But sometimes the promises are being resolved when the component view is already destroyed, eg user closed tab (internal tab of our app). In that case I am getting ViewDestroyedError: Attempt to use a destroyed view: detectChanges. Even though I have detached the view on destroy phase of my tab.component. My question is what am I doing wrong here?

I have tried to detach the view from change detection on destroy phase with no luck, promise is being resolved after destroy phase and detectChanges is still called. I do understand that ngOnDestroy is not actually destroying the class and that the code inside of it will be destroyed on garbage collection phase.

here is an example code from my tab.component that causes the issue

const promises:Promise<any>[] = [];
_.each(types, (type:string) => {
  promises.push(this.service.getResultsBy(type))
})
Promise.all(promises)
.then((data) => {
  //some code here
  this.cd.detectChanges();
})

and in ngOnDestroy I am detaching the view from C.D

ngOnDestroy() {
    this.cd.detach();
  }

The promises are important for me in this case, cause I do need to do some calculations/state saving even if the component is destroyed. I just want to understand how can I detach the view good enough so that my code inside the promise will not cause change detection attempts.

Narek Gevorgyan
  • 113
  • 1
  • 12

1 Answers1

3

Detaching from change detection on ngOnDestroy is not needed and will not help with this error. However, you cannot call detectChanges after ngOnDestroy has been called. With observables you can unsubscribe from the observable in ngOnDestroy. There is no way to unsubscribe from a Promise so you will need to keep a flag in your component instead.

export class MyComponent {

  private destroyed = false;

  ngOnDestroy() {
    this.destroyed = true;
  }

  triggerChangeDetection() {
    if (!this.destroyed) {
      this.cd.detectChanges();
    }
  }

}
Pace
  • 41,875
  • 13
  • 113
  • 156
  • I thought If I am detaching from change detection Angular will understand that view is already detached and will not try to update it, but I agree it is not helping. I ended up checking if the view is destroyed or not inside my promise like this ' `if (this.cdRef["destroyed"]) { // my code here}`. Almost the same thing as you are saying, just not keeping a flag. Thanks a lot for your answer, I'll keep this question unresolved in case somebody will offer a better solution. – Narek Gevorgyan May 11 '19 at 12:16
  • Understood. Detaching from change detection will prevent Angular from calling `detectChanges` but it will not stop you or support manually calling `detectChanges` yourself. It wouldn't be useful otherwise. It's intended for use cases where the app developer knows how to trigger change detection more efficiently so developers can detach and then call `detectChanges` on their own. – Pace May 11 '19 at 16:00