Попытка использовать разрушенное представление: событие detectChanges, несмотря на то, что представление отсоединено

У меня есть компонент, который выполняет некоторые сервисные вызовы и получает обещания. После того, как промисы разрешены, я делаю detectChanges. Но иногда обещания разрешаются, когда представление компонента уже уничтожено, например, закрытая пользователем вкладка (внутренняя вкладка нашего приложения). В этом случае я получаю ViewDestroyedError: Attempt to use a destroyed view: detectChanges. Несмотря на то, что я отсоединил представление об фазе уничтожения моего tab.component. Мой вопрос в том, что я делаю неправильно здесь?

Я безуспешно пытался отсоединить представление от обнаружения изменений на этапе уничтожения, обещание разрешается после этапа уничтожения, а detectChanges все еще вызывается. Я понимаю, что ngOnDestroy на самом деле не уничтожает класс и что код внутри него будет уничтожен на этапе сборки мусора.

вот пример кода из моего tab.component, который вызывает проблему

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();
})

а в ngOnDestroy я отсоединяю вид от C.D

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

Обещания важны для меня в этом случае, потому что мне нужно выполнить некоторые вычисления/сохранение состояния, даже если компонент будет уничтожен. Я просто хочу понять, как я могу достаточно хорошо отсоединить представление, чтобы мой код внутри обещания не вызывал попыток обнаружения изменений.


person Narek Gevorgyan    schedule 09.05.2019    source источник


Ответы (1)


Отключение от обнаружения изменений на ngOnDestroy не требуется и не поможет при этой ошибке. Однако вы не можете вызвать detectChanges после вызова ngOnDestroy. С наблюдаемыми вы можете отказаться от подписки на наблюдаемые в ngOnDestroy. Невозможно отписаться от Promise, поэтому вместо этого вам нужно будет сохранить флаг в своем компоненте.

export class MyComponent {

  private destroyed = false;

  ngOnDestroy() {
    this.destroyed = true;
  }

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

}
person Pace    schedule 09.05.2019
comment
Я думал, что если я отключусь от обнаружения изменений, Angular поймет, что представление уже отсоединено, и не будет пытаться его обновить, но я согласен, что это не помогает. Я закончил тем, что проверил, уничтожено ли представление или нет внутри моего обещания, как это ' if (this.cdRef["destroyed"]) { // my code here}. Почти то же самое, что вы говорите, только флаг не держит. Большое спасибо за ваш ответ, я оставлю этот вопрос нерешенным, если кто-то предложит лучшее решение. - person Narek Gevorgyan; 11.05.2019
comment
Понял. Отключение от обнаружения изменений не позволит Angular вызывать detectChanges, но не остановит вас и не поддержит ручной вызов detectChanges самостоятельно. Иначе это было бы бесполезно. Он предназначен для случаев использования, когда разработчик приложения знает, как более эффективно инициировать обнаружение изменений, чтобы разработчики могли отсоединиться, а затем вызвать detectChanges самостоятельно. - person Pace; 11.05.2019