ExpressionChangedAfterItHasBeenCheckedError при загрузке индикатора

avatar
Ralf de Kleine
19 апреля 2018 в 07:10
600
2
1

Я получаю сообщение об ошибке в индикаторе загрузки, и я не понимаю почему:

LoadingIndicatorComponent.html:2 ERROR Ошибка: ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки. Предыдущее значение: «скрыто: правда». Текущее значение: «скрыто: ложь».

У меня есть простое изображение индикатора загрузки:

<img class="loader" [hidden]="!isLoading" src="loading.svg" alt="Loading..." />

Со следующим кодом:

export class LoadingIndicatorComponent implements OnInit {
  public isLoading = false;
  constructor(private loader: LoadingIndicatorService) {
  }

  ngOnInit() {
    this.loader.IsLoading.subscribe((value) => {
      this.isLoading = value;
    });
  }
}

Что использует следующий сервис:

export class LoadingIndicatorService {
  constructor() { }

  private workload = 0;
  private _loading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
  public readonly IsLoading: Observable<boolean> = this._loading.asObservable();

  public StartWork(): void {
    this.workload++;
    this._loading.next(this.workload > 0);
  }

  public EndWork(): void {
    this.workload--;
    this._loading.next(this.workload > 0);
  }
}
Источник
Gregor Doroschenko
19 апреля 2018 в 07:17
0

Вот очень хорошее исследование этой проблемы в angular. coderhelper.com/questions/44691745/…

Ответы (2)

avatar
Pranay Rana
19 апреля 2018 в 07:23
1

Вы изменяете значение isLoading во время цикла обнаружения изменений, что вызывает проблему. что это за строка кода

this.loader.IsLoading.subscribe((value) => {
  this.isLoading = value;
});

загружается измененный вами сервис. поэтому вам нужно обойти это

this.loader.IsLoading.subscribe((value) => {
 Promise.resolve(null).then(() =>  this.isLoading = value);
});

ответ основан на этом сообщении: Все, что вам нужно знать об ошибке ExpressionChangedAfterItHasBeenCheckedError

Ralf de Kleine
19 апреля 2018 в 07:27
0

Я наткнулся на статью, которую вы упомянули, и не совсем понял ее суть. Потребуется еще некоторое время, чтобы понять это лучше. Ваше решение помогает, хотя :)

avatar
MD KAMRUL HASAN SHAHED
19 апреля 2018 в 07:14
0

Я тоже столкнулся с такой проблемой. Используйте это

this.loader.IsLoading.subscribe((value) => {
    setTimeout(() => this.isLoading = value, 0)
});
Gregor Doroschenko
19 апреля 2018 в 07:18
1

Это всего лишь обходной путь, а не хорошее решение. Прочтите эту статью (blog.angularindepth.com/…), чтобы понять, как работает обнаружение изменений в angular.

MD KAMRUL HASAN SHAHED
19 апреля 2018 в 07:27
0

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

Gregor Doroschenko
19 апреля 2018 в 07:39
1

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