我正尝试使用此处列出的ErrorHandler来全局处理角度错误:https://medium.com/@aleixsuau/error-handling-angular-859d529fa53a
我正在将错误消息转发到通知服务。应用程序组件模板已使用异步管道绑定到服务提供的可观察对象。
引发客户端错误时,一切都会按预期进行:捕获错误,发送通知,并且UI显示错误消息。 3秒钟后,该消息消失,因为可观察到的值变为空值。
在HttpErrorResponses上,行为很奇怪:捕获了错误,发送了通知,但UI不更新。除非在3秒内引发另一个HttpErrorResponse!
我是否缺少某些东西,或者这是Angular 6或RxJs中的错误?
我在stackblitz上创建了一个最小,完整且可验证的示例: https://stackblitz.com/edit/angular-e9keuw
ErrorHandler:
@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}`);
}
}
NotificationService:
@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);
}
}
组件:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
constructor(
private notificationService: NotificationService,
private http: HttpClient
) {}
throwError(): void {
throw new Error('an error was thrown!');
}
loadUrl() {
this.http.get('https://www.google.com/').subscribe(
data => console.log(data)
);
}
}
和绑定的模板:
<div *ngIf="notificationService.notification$ | async as notification">
{{ notification }}
</div>
答案 0 :(得分:3)
原因是错误是在区域外触发的。我不知道发生这种情况的确切原因,因为我看不到您的所有代码,但这是:)。更新您的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);
});
}
}
不过有一个提示,请将您的setTimeout引用保存在类成员中。这样,如果您在3秒内遇到两个错误,则可以取消setTimeout。可能发生第二个错误,因为它已经设置为null