Angular 角度6:HttpErrorResponse后可观察到的异步绑定未按预期工作
我正在尝试使用ErrorHandler全局处理angular中的错误,如下所示: 我正在将错误消息转发到通知服务。应用程序组件模板绑定到由使用异步管道的服务提供的可观察组件 当抛出客户机错误时,一切都按预期进行:捕获错误,发送通知,UI显示错误消息。3秒钟后,消息消失,因为可观察值变为空值 在HttpErrorResponses上,行为很奇怪:捕获错误,发送通知,但UI不更新。除非在3秒内抛出另一个HttpErrorResponse 我是否遗漏了什么,或者这是Angular 6或RxJs中的一个bug 我在stackblitz上创建了一个最小、完整且可验证的示例: ErrorHandler:Angular 角度6:HttpErrorResponse后可观察到的异步绑定未按预期工作,angular,error-handling,rxjs,Angular,Error Handling,Rxjs,我正在尝试使用ErrorHandler全局处理angular中的错误,如下所示: 我正在将错误消息转发到通知服务。应用程序组件模板绑定到由使用异步管道的服务提供的可观察组件 当抛出客户机错误时,一切都按预期进行:捕获错误,发送通知,UI显示错误消息。3秒钟后,消息消失,因为可观察值变为空值 在HttpErrorResponses上,行为很奇怪:捕获错误,发送通知,但UI不更新。除非在3秒内抛出另一个HttpErrorResponse 我是否遗漏了什么,或者这是Angular 6或RxJs中的一个
@Injectable()
export class ErrorSink implements ErrorHandler {
// ErrorHandler is created before the providers
// we have to use the Injector to get them
constructor(private injector: Injector) {}
handleError(error: Error | HttpErrorResponse) {
console.error('Caught error: ', error);
const notificationService = this.injector.get(NotificationService);
// client error
if (!(error instanceof HttpErrorResponse)) {
console.log('client error!');
return notificationService.notify(error.message);
}
// offline error
if (!navigator.onLine) {
console.log('No Internet Connection');
return notificationService.notify('No Internet Connection');
}
// http error
console.log(error.status, error.message);
return notificationService.notify(`${error.status} - ${error.message}`);
}
}
通知服务:
@Injectable()
export class NotificationService {
private subject: BehaviorSubject<string> = new BehaviorSubject(null);
readonly notification$: Observable<string> = this.subject.asObservable();
constructor() {}
notify(message) {
console.log('notification', message)
this.subject.next(message);
setTimeout(() => this.subject.next(null), 3000);
}
}
和绑定模板:
<div *ngIf="notificationService.notification$ | async as notification">
{{ notification }}
</div>
{{通知}}
原因是错误在区域外触发。我不知道发生这种情况的确切原因,因为我没有看到您的所有代码,但它是:)。更新NotificationService以在区域内运行通知:
@Injectable()
export class NotificationService {
private subject: BehaviorSubject<string> = new BehaviorSubject(null);
readonly notification$: Observable<string> = this.subject.asObservable();
private timeout: number = 0;
constructor(readonly zone: NgZone) {}
notify(message) {
console.log('notification', message)
clearTimeout(this.timeout);
this.zone.run(() => {
this.subject.next(message);
this.timeout = setTimeout(() => this.subject.next(null), 3000);
});
}
}
@Injectable()
出口类通知服务{
私有主体:BehaviorSubject=新的BehaviorSubject(空);
只读通知$:Observable=this.subject.asObservable();
私有超时:数字=0;
构造函数(只读区域:NgZone){}
通知(信息){
console.log('通知',消息)
clearTimeout(this.timeout);
此.zone.run(()=>{
this.subject.next(消息);
this.timeout=setTimeout(()=>this.subject.next(null),3000);
});
}
}
不过有一个提示,将setTimeout引用保存在类成员中。这样,如果在3秒内出现两个错误,可以取消设置超时。第二个错误可能无法读取,因为它已设置为null。原因是该错误在区域外触发。我不知道发生这种情况的确切原因,因为我没有看到您的所有代码,但它是:)。更新NotificationService以在区域内运行通知:
@Injectable()
export class NotificationService {
private subject: BehaviorSubject<string> = new BehaviorSubject(null);
readonly notification$: Observable<string> = this.subject.asObservable();
private timeout: number = 0;
constructor(readonly zone: NgZone) {}
notify(message) {
console.log('notification', message)
clearTimeout(this.timeout);
this.zone.run(() => {
this.subject.next(message);
this.timeout = setTimeout(() => this.subject.next(null), 3000);
});
}
}
@Injectable()
出口类通知服务{
私有主体:BehaviorSubject=新的BehaviorSubject(空);
只读通知$:Observable=this.subject.asObservable();
私有超时:数字=0;
构造函数(只读区域:NgZone){}
通知(信息){
console.log('通知',消息)
clearTimeout(this.timeout);
此.zone.run(()=>{
this.subject.next(消息);
this.timeout=setTimeout(()=>this.subject.next(null),3000);
});
}
}
不过有一个提示,将setTimeout引用保存在类成员中。这样,如果在3秒内出现两个错误,可以取消设置超时。第二个错误可能无法读取,因为它已设置为null这确实有效。知道为什么第二个http错误会在区域内运行吗?第二次单击会触发更改检测,而不是错误本身:)@MarkusDresch您可以通过向组件中的另一个元素添加一个单击侦听器来测试这一点。这确实有效。知道为什么第二个http错误会在区域内运行吗?第二次单击会触发更改检测,而不是错误本身:)@MarkusDresch您可以通过向组件中的另一个元素添加单击侦听器来测试这一点