使用BehaviorSubject从服务更新Angular组件



我正试图显示/隐藏一个基于服务上的变量的ng容器。应该在全局错误处理程序中更改该值,该处理程序应该捕获我的应用程序上的所有异常。

在我的服务中,我创建了一个变量,将我的BehaviorSubject公开为可观察的。

export class ErrorsService {
private notify = new BehaviorSubject(false);
// Subscribe to cast in the component
cast = this.notify.asObservable();
// Change notify value
notifyError(){
this.notify.next(true);
}
constructor() { }
}

我在全局错误处理程序中注入了此服务,以便调用notifyError((,如下所示:

export class GlobalErrorHandler implements ErrorHandler {
constructor(private errorService: ErrorsService) { }
handleError(error: any) {
// Notify subscribers
this.errorService.notifyError();

//continue handling the error
}
}

在我的组件中,我使用相同的服务来订阅变量";铸造";并更改局部变量show。

export class ErrorsBlockComponent implements OnInit {
show = false;
constructor(private errorsService:ErrorsService) {}
ngOnInit(): void {
this.errorsService.cast.subscribe(value=>{
this.show = value;
});
}

}

最后,我的组件的html看起来像

<ng-container *ngIf="show">There is an Error!</ng-container>

视图不会更新,直到我点击一个按钮!(应用程序中的任何按钮(。show值已更改为true,但视图似乎没有更新。

我的问题是,当服务值按预期更新时,为什么视图没有更新?当我使用console.log(value(时,我可以看到该值变为true,但在按下按钮之前,UI上不会发生任何事情。


更新:

我在StackBlitz 上复制了这个问题

https://stackblitz.com/edit/angular-ivy-j7thwx?file=src/app/app.component.ts

我还使用了ChangeDetectorRef.detectChanges((,它似乎解决了这个问题。然而,我想知道为什么没有它就不起作用,因为这个项目是为了学习。

这是因为您的代码运行在角度区域之外。如果在角区外发生任何事情,您需要运行NgZone来推动您的更改。

以下是如何检查代码行是否在NgZone内。

NgZone.isInAngularZone()

在你的情况下,你可以做

ngOnInit() {
console.log('Outside subscription Is in angular zone: ' + NgZone.isInAngularZone());
// Subscribe to error service
this.errorsService.cast.subscribe((value) => {
this.show = value;
console.log('Within subscription Is in angular zone: ' + NgZone.isInAngularZone());
});
// The getSomething call is going to throw an error
this.anotherService
.getSomthing()
.subscribe((result) => (this.result = result));
}

检查更新的stackblitz

要触发对的更改

this.ngZone.run( () => {
this.show = value;
});

如所述

public notify = new BehaviorSubject<boolean>(false);
notifyError(val){
this.notify.next(val)
}

你可以订阅

this.errorsService.notify.subscribe(res=>{
this.error=res
}

你可以尝试一次,你没有做错,没有看到太多为什么它不起作用

最新更新