问题
I have this code:
import {Injectable, ExceptionHandler, SkipSelf, Host, Optional} from '@angular/core';
import {ToastNotification} from '../toast-messages/toastNotification.service';
export class UIError extends Error {
constructor (private toastMessage: string) {
super();
this.toastMessage = toastMessage;
}
}
export class MyUIError extends UIError {}
export class AnotherError extends UIError {}
export class _ArrayLogger {
res = [];
log(s: any): void { this.res.push(s); }
logError(s: any): void { this.res.push(s); }
logGroup(s: any): void { this.res.push(s); }
logGroupEnd() {};
}
export class ConsoleLogger {
log(s: any): void {console.log(s);}
}
@Injectable()
export class CustomExceptionHandler extends ExceptionHandler {
constructor(private logger: ConsoleLogger, private toast: ToastNotification) {
super (new _ArrayLogger(), true);
}
call(exception: any, stackTrace = null, reason = null) {
let self = this;
if (exception.originalException instanceof UIError) {
self.toast.Error(exception.originalException.toastMessage);
} else {
this.logger.log(exception);
}
}
}
When I try to run this, I have problem with toast: ToastNotification. The error I get is:
zone.js:260Uncaught EXCEPTION: Error during instantiation of ApplicationRef_! (ApplicationRef -> ApplicationRef_).
ORIGINAL EXCEPTION: Cannot instantiate cyclic dependency! (ExceptionHandler -> ToastNotification)
ORIGINAL STACKTRACE:
Error: DI Exception
at CyclicDependencyError.BaseException
I inject this component in the boostrap also. How could this be solved?
回答1:
I still had the same issue when using injector in constructor. What solved it for me was moving the injection part to the call function.
@Injectable()
export class AppExceptionHandler extends ExceptionHandler {
private router:Router;
private toaster:ToastsManager;
constructor(private injector: Injector) {
super(new _ArrayLogger(), true);
}
call(exception:any, stackTrace?:any, reason?:string):void {
this.getDependencies();
console.log(exception);
if(exception.status === 401){
// Show login
this.router.navigate(['/login']);
}
// Get error messages if http exception
let msgs = [];
if(exception instanceof Response){
msgs = this.getMessagesFromResponse(exception);
}else{
// Otherwise show generic error
msgs.push('Something went wrong');
}
// Show messages
msgs.forEach((msg) => this.toaster.error(msg));
super.call(exception, stackTrace, reason);
}
private getDependencies(){
if(!this.router){
this.router = this.injector.get(Router);
}
if(!this.toaster){
this.toaster = this.injector.get(ToastsManager);
}
}
}
回答2:
After seeing this question How to Inject my service to ExceptionHandler I think this could be a solution for your problem. If you control one of the classes of the cyclic depenencies, you can just inject the Injector
to the constructor and then acquire the instance you actually want:
constructor(injector:Injector) {
setTimeout(() => this.someService = injector.get(SomeService));
}
来源:https://stackoverflow.com/questions/37592078/cyclic-dependency-when-ovveriding-exceptionhandler