Обнаружение угловых изменений ExpressionChangedAfterItHasBeenCheckedError с асинхронным каналом

#angular

Вопрос:

У меня есть компонент загрузчика, который работает с перехватчиком:

Компонент загрузчика:

 import { Component } from '@angular/core';
import { LoaderService } from '../../services/loader.service';

@Component({
    selector: 'app-loader',
    templateUrl: './loader.component.html',
    styleUrls: ['loader.component.css'],
})
export class LoaderComponent {
    isLoading = this.loaderService.isLoading;

    constructor(private loaderService: LoaderService) {}
}

<div class="overlay" *ngIf="isLoading | async">
    <div class="lds-hourglass"></div>
</div>
 

Услуги погрузчика:

 import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
    providedIn: 'root',
})
export class LoaderService {
    private _isLoading = new BehaviorSubject<boolean>(false);
    isLoading = this._isLoading.asObservable();

    setLoading(isLoading: boolean) {
        this._isLoading.next(isLoading);
    }
}
 

Перехватчик погрузчика:

 import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { LoaderService } from '../services/loader.service';

@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
    private totalRequests = 0;

    constructor(private loaderService: LoaderService) {}

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.totalRequests  ;
        this.loaderService.setLoading(true);

        return next.handle(req).pipe(
            finalize(() => {
                this.totalRequests--;

                if (this.totalRequests === 0) {
                    this.loaderService.setLoading(false);
                }
            })
        );
    }
}
 

Я получаю:
Выражение изменено, если ошибка была проверена

Но я не меняю привязку после ее рендеринга, почему я получаю эту ошибку?

EDIT

If i use ngOnInit to initialize isLoading observable in Loader component, error still happening

EDIT

Finally i ended up with this solution:

Loader component:

 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { LoaderService } from '../../services/loader.service';

@Component({
    selector: 'app-loader',
    templateUrl: './loader.component.html',
    styleUrls: ['loader.component.css'],
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoaderComponent implements OnInit, OnDestroy {
    isLoading = false;
    private subs: Subscription[] = [];

    constructor(private loaderService: LoaderService, private changeDetectorRef: ChangeDetectorRef) {}

    ngOnInit() {
        const sub = this.loaderService.isLoading.subscribe((res) => {
            this.isLoading = res;
            this.changeDetectorRef.detectChanges();
        });
        this.subs.push(sub);
    }

    ngOnDestroy() {
        this.subs.forEach((sub) => sub.unsubscribe());
    }
}
 

Услуги погрузчика:

 import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
    providedIn: 'root',
})
export class LoaderService {
    isLoading = new BehaviorSubject<boolean>(false);

    setLoading(isLoading: boolean) {
        this.isLoading.next(isLoading);
    }
}
 

Это работает, потому что со стратегией OnPush мы говорим, чтобы изменить цикл обнаружения для визуализации, когда мы хотим явно с this.changeDetectorRef.detectChanges();

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

Комментарии:

1. ‘Простое’ исправление, вероятно, состояло бы в том, чтобы обернуть это._isLoading.next(загружается); в setTimeout (с 0 временем). Может быть, это и не очень красиво, но обычно это работает нормально.

2. Да, я знаю, что это работает, потому что асинхронно, но это как-то странно