【问题标题】:Cyclic dependency , when ovveriding ExceptionHandler [duplicate]循环依赖,当 ovveriding ExceptionHandler [重复]
【发布时间】:2016-10-02 04:53:26
【问题描述】:

我有这个代码:

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);
        }
    }
}

当我尝试运行它时,我遇到了 toast 的问题:ToastNotification。我得到的错误是:

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

我也在 boostrap 中注入了这个组件。怎么解决?

【问题讨论】:

  • 这是否意味着ToastNotification 作为ExceptionHandler 作为构造函数参数?
  • 是的,它有一个 AppRef 的引用,在它的树中有一些 ExceptionHandler 组件 :( 处理这个问题的最佳方法是什么?
  • 我想不要将ExceptionHandler 注入到ToastNotification DI 无法应对循环依赖。对于构造函数注入,这在技术上是不可能的。您可以在 Angular 之外创建实例并强制解决循环依赖关系,方法是仅使用 ToastNotification 上的属性,其中 ExceptionHandler 在实例化后分配,然后使用 provide(..., {useValue: ...}) 提供所有相关实例,但这非常难看。

标签: javascript angularjs dependency-injection typescript angular


【解决方案1】:

看到这个问题How to Inject my service to ExceptionHandler 后,我认为这可能是您的问题的解决方案。如果您控制循环依赖的类之一,您只需将Injector 注入构造函数,然后获取您真正想要的实例:

constructor(injector:Injector) {
  setTimeout(() => this.someService = injector.get(SomeService));
}

【讨论】:

    【解决方案2】:

    在构造函数中使用注入器时我仍然遇到同样的问题。为我解决的问题是将注入部分移至调用函数。

    @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);
        }
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-15
      • 2018-04-21
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多