我正在尝试在Angular 2应用程序中实现自定义ExceptionHandler
,该应用程序将未捕获的错误提交给自定义AlertsService
。目的是允许主要App
组件订阅AlertsService
提供的警报,以便它可以在UI中显示错误。
我看到的问题是,在遇到另一个错误之前,自定义AlertsService
提交给ExceptionHandler
的错误不会反射(reflect)在UI中。这导致UI始终是AlertsService
实际提供的内容背后的一个警报。
我的猜测是,此行为与更改检测和ExceptionHandler的特殊情况有关,但是我不确定从这里开始。向Angular2专家寻求帮助!
下面的示例代码,plunk here:
import { Component, ExceptionHandler, Injectable, OnInit, provide } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';
import { Subject } from 'rxjs/Subject'
export interface Alert {
message: string;
}
@Injectable()
export class AlertsService {
private alertTriggeredSubject = new Subject<Alert>();
alertTriggered = this.alertTriggeredSubject.asObservable();
triggerAlert(message: string) {
this.alertTriggeredSubject.next(<Alert>{ message: message });
}
}
@Injectable()
export class CustomExceptionHander {
constructor(private alertsService: AlertsService) { }
call(exception, stackTrace = null, reason = null) {
this.alertsService.triggerAlert(exception.originalException);
console.error('EXCEPTION:', exception);
}
}
@Component({
selector: 'child-component',
template : `
<h3>Child</h3>
<div id="child">
<button (click)="breakMe()">Break Me!</button>
<div>Alerts Sent:</div>
<ul><li *ngFor="let error of errors">{{error}}</li></ul>
</div>`
})
export class ChildComponent {
errors: string[] = [];
numErrors = 0
breakMe() {
this.numErrors++;
let error = `I broke it (${this.numErrors})`;
// The error added to the array below is never reflected in the
// "Alerts Sent:" <ul>...not sure why
this.errors.push(error);
console.info('ChildComponent.errors', this.errors);
// Simulate unhandled exception
throw new Error(error);
}
}
@Component({
selector: 'my-app',
template : `
<h3>Parent</h3>
<div id="parent">
<div>Alerts Received:</div>
<ul><li *ngFor="let alert of alerts">{{alert.message}}</li></ul>
<child-component></child-component>
</div>`
directives: [ChildComponent]
})
export class App implements OnInit {
constructor(private alertsService: AlertsService) { }
alerts: Alert[] = [];
ngOnInit() {
this.alertsService.alertTriggered.subscribe(alert => {
this.alerts.push(alert);
// Alert gets received, but is not reflected in the UI
// until the next alert is received, even thought the
// alerts[] is up-to-date.
console.info('App alert received:', alert);
console.info('App.alerts:', this.alerts);
});
}
}
bootstrap(App, [
AlertsService,
provide(ExceptionHandler, { useClass: CustomExceptionHander })
]).catch(err => console.error(err));
最佳答案
更新 ExceptionHandler
重命名为ErrorHandler
https://stackoverflow.com/a/35239028/217408
原始
处理程序引发时,更改检测不会在click
事件的末尾运行。
您可以手动调用更改检测,但这会变得有些复杂,因为您需要ApplicationRef
引用,并且ApplicationRef
取决于ExceptionHandler
,这使整个周期整齐,并且DI无法解决循环依赖性。
一种解决方法是代替ApplicationRef
注入(inject)Injector
并强制性地获取AplicationRef
,例如
constructor(private alertsService: AlertsService, injector:Injector) {
setTimeout(() => this.appRef = injector.get(ApplicationRef));
}
然后在
call
中调用更改检测,例如call(exception, stackTrace = null, reason = null) {
this.alertsService.triggerAlert(exception.originalException);
this.appRef.tick();
console.error('EXCEPTION:', exception);
}
Plunker example
关于angular - 自定义ExceptionHandler更改检测滞后,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37793276/