我正在尝试在我的angular应用程序中实现一个简单的异常处理程序,但是在最后一步遇到了问题,我想在该步骤中通过primeng对话框向用户显示消息。 为了测试目的,我有一个控制器端点,在这里我只是抛出一个异常。这会遇到我的http拦截器,然后进入异常处理程序,在这里我调用通知服务的showError()方法,该方法的Subjects发出displayModal true和消息字符串。在错误模式组件中,我订阅了这些主题。在控制台从应用程序中注销后,似乎在我将true分配给对话框组件showDialog变量后,不运行可见性检查,因此仅在页面上发生其他事件后,对话框窗口才可见。这是代码。
拦截器:
@Injectable()
export class ServerErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
// retry the HTTP call once
retry(1),
catchError((error: HttpErrorResponse) => {
//check statuses if you want
if (error.status === 418) {
// do whatever you want
} else {
return throwError(error);
}
})
);
}
}
ErrorHandler:
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
constructor(private injector: Injector) { }
handleError(error: Error | HttpErrorResponse) {
const errorService = this.injector.get(ErrorService);
const logger = this.injector.get(LoggingService);
const notifier = this.injector.get(NotificationService);
let message;
let stackTrace;
if (error instanceof HttpErrorResponse) {
message = errorService.getServerMessage(error);
console.log(error.error.message);
stackTrace = errorService.getServerStack(error);
notifier.showError(message);
} else {
message = errorService.getClientMessage(error);
stackTrace = errorService.getClientStack(error);
notifier.showError(message);
}
logger.logError(message, stackTrace);
console.error(error);
}
}
NotificationService:
@Injectable({
providedIn: 'root'
})
export class NotificationService {
// TODO: implement a proper NotificationService!
//displayModal: Subject<boolean> = new Subject();
displayModal: Subject<boolean> = new Subject();
message: Subject<string> = new Subject();
constructor() { }
showSuccess(message: string): void {
alert(message);
}
public showError(message: string): void {
this.message.next(message);
this.displayModal.next(true);
}
}
ErrorModalComponent:
@Component({
selector: 'app-error-modal',
templateUrl: './error-modal.component.html',
styleUrls: ['./error-modal.component.css']
})
export class ErrorModalComponent implements OnInit {
constructor(private notificationService: NotificationService) {}
displayModalSubcription: Subscription;
messageSub: Subscription;
displayModal: boolean = false;
message: string;
ngOnInit() {
this.messageSub = this.notificationService.message.subscribe(message => {
this.message = message;
});
this.displayModalSubcription = this.notificationService.displayModal
.subscribe(displayModal => {
this.displayModal = displayModal;
});
}
}
对话框模板:
<p-dialog [contentStyle]="{'overflow':'visible'}" modal="true" header="Error occured" [(visible)]="displayModal" >
{{message}}
</p-dialog>
如果我省去了http调用,而只是将notificationService.showError()绑定到按钮上,它就可以工作,这就是为什么我认为它必须与http调用的异步行为有关,但是我不确定,因为事实上我已经出错了,这意味着我已经响应了http调用...我对angular非常陌生,所以仍然有一些模糊的字段。
非常感谢您的帮助!
答案 0 :(得分:0)
您的通知服务已标记为private
,并且您在视图中引用了该服务。那应该给你一个错误。
此ErrorModalComponent
必须一直处于当前视图中(无论您所处的路线如何)。
尝试一下:
NotificationService:
@Injectable({
providedIn: 'root'
})
export class NotificationService {
// TODO: implement a proper NotificationService!
displayModal = new BehaviorSubject<boolean>(false);
message = new BehaviorSubject<string>();
constructor() { }
showSuccess(message: string): void {
alert(message);
}
public showError(message: string): void {
this.message.next(message);
this.displayModal.next(true);
}
public hideError(): void {
this.displayModal.next(false);
}
}
ErrorModalComponent:
@Component({
selector: 'app-error-modal',
templateUrl: './error-modal.component.html',
styleUrls: ['./error-modal.component.css']
})
export class ErrorModalComponent implements OnInit {
showModal: boolean;
message: string;
constructor(private notificationService: NotificationService) {}
ngOnInit() {
this.notificationService.displayModal.subscribe(v => this.showModal = v);
this.notificationService.message.subscribe(m => this.message = m);
}
}
查看:
<p-dialog [contentStyle]="{'overflow':'visible'}"
modal="true"
header="Error occured"
[(visible)]="showModal" >
{{message}}
</p-dialog>
您的情态需要一些东西来关闭它。将该按钮绑定到组件中的本地closeModal
函数,然后从那里调用hideModal
的{{1}}函数。
希望对您有帮助。
答案 1 :(得分:0)
这可能是一种解决方法,但至少可以。在将displayModal和message设置为true之后,我用ChangeDetectorRef
强制进行更改检测:
@Component({
selector: 'app-error-modal',
templateUrl: './error-modal.component.html',
styleUrls: ['./error-modal.component.css']
})
export class ErrorModalComponent implements OnInit, OnDestroy {
displayModalSubcription: Subscription;
messageSub: Subscription;
displayModal: boolean = false;
message: string;
constructor(private notificationService: NotificationService, private cdRef: ChangeDetectorRef) {}
ngOnInit() {
this.messageSub = this.notificationService.message.subscribe(message => {
this.message = message;
this.cdRef.detectChanges();
});
this.displayModalSubcription = this.notificationService.displayModal.subscribe(displayModal => {
this.displayModal = displayModal;
this.cdRef.detectChanges();
});
}
ngOnDestroy() {
this.displayModalSubcription.unsubscribe();
}
}