gpt4 book ai didi

angular - ExpressionChangedAfterItHasBeenCheckedError Angular

转载 作者:行者123 更新时间:2023-12-03 08:38:41 27 4
gpt4 key购买 nike

我正在为我的项目集成一个加载指示器,其可见性将在 HTTP 拦截器服务中集中确定。但是,实现后,我收到以下错误:

 ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'null'. Current value: 'true'.

以下是我的精简文件:

app.component.ts

import { SpinnerService } from '@app/services/spinner.service';
import { Subject } from 'rxjs';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnDestroy {
title = 'My App';
isLoading: Subject<boolean> = this.spinnerService.isLoading;

constructor(public spinnerService: SpinnerService) {
}

}

app.component.html

<div class="example-container" [class.example-is-mobile]="mobileQuery.matches">
<router-outlet></router-outlet>
<div *ngIf="isLoading | async" class="overlay">
Loading
</div>
</div>

spinner.service.ts

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

@Injectable()

export class SpinnerService {

isLoading = new Subject<boolean>();

constructor() {
}

show() {
this.isLoading.next(true);
}

hide() {
this.isLoading.next(false);
}
}

拦截器.service.ts

import { Injectable } from '@angular/core';
import {HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse} from '@angular/common/http';
import {EMPTY, Observable, throwError} from 'rxjs';

import { environment } from '@env/environment';
import { finalize } from 'rxjs/operators';
import { SpinnerService } from '@app/services/spinner.service';

@Injectable()
export class JwtInterceptor implements HttpInterceptor {

// snackBar: MatSnackBar;

constructor(public spinnerService: SpinnerService) { }

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.spinnerService.show();

return next.handle(request).pipe(
finalize(() => this.spinnerService.hide()),
);
}
}

最后,我的其他组件中的示例用法如下:

        this.http.get(`${environment.apiUrl}/form/schema/days`)
.subscribe(data => {
console.log('done', data);
});

我不知道我在这里做错了什么,有人可以解释一下吗?

最佳答案

理想情况下,您应该调用 NgOnInit Hook 内的数据源,这可以防止出现此问题。解决此问题的一种方法是使用 RXJS 延迟运算符使加载程序值更改在当前组件初始化周期之外发生:

isLoadingSubject = = new Subject<boolean>();
isLoading: Observable<boolean> = this.isLoadingSubject.pipe( delay(0) );

我认为这是一个相关的阅读:https://blog.angular-university.io/angular-debugging/

更新以在代码的第二行上解压一下:

Angular 功能变化检测 - 这是一个由以下因素触发的过程:

  • 输入事件(点击、鼠标悬停、按键等)
  • Ajax 请求
  • setTimeout() 和 setInterval()

然后它会遍历应用程序的组件树,检查所有数据绑定(bind)(取决于 CD 策略等)。

当在同一更改检测周期内,Angular 检测到绑定(bind)值在对该绑定(bind)执行更改检查后已经发生更改时,就会发生您看到的错误,从而导致 Angular 出现问题,因为它无法更新绑定(bind)值相应的模板。

因此,为了解决这样的问题,我们可以确保更改在特定 CD 周期开始之前发生(有时我们可以通过将数据更改操作移动到不同的组件生命周期 Hook 来实现)或延迟它 - 确保更改将在在下一个周期执行。

RXJS 的延迟使用了 setTimeout(),如上所述,它确实触发了它自己的另一个 CD 周期。主题是一个可观察的对象,可以多播到多个观察者。因此,我们通过管道将其设置为“延迟”,从而为该特定更改保留 CD 周期。

所以,如果我们迂腐的话——这更像是一种有效的解决方法。但代价是我们在这里运行的另一个 CD 周期。

关于angular - ExpressionChangedAfterItHasBeenCheckedError Angular ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63229070/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com