Angular 2 RC 2如何将路由器注入自定义ExceptionHandler

时间:2016-06-17 10:46:31

标签: angular angular2-routing

我正在使用Angular 2 RC2。我需要将Angular 2路由器注入我的自定义ExceptionHandler类。但是我收到以下错误

  

错误:错误:无法解析' ErrorHandler'(?)的所有参数。   确保所有参数都使用Inject或者装饰   有效的类型注释和那个' ErrorHandler'装饰着   可注射的。

我确实试过装饰私有路由器:使用@Inject的路由器无济于事。我使用打字稿,因此我认为我不需要@Inject属性。

我的自定义ExceptionHandler看起来像这样

import { ExceptionHandler } from '@angular/core';
import { Router } from '@angular/router';

export class ErrorHandler extends ExceptionHandler{

    constructor(
        private router: Router 
    ){
        super(null, null);

    }

    call(error, stackTrace = null, reason = null) {
        console.log(error);
        this.router.navigate(['/error']);
    }
}

我的main.ts看起来像这样

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';

import { provide, ExceptionHandler } from '@angular/core';
import { ErrorHandler } from './error-handler/error-handler';

import { HTTP_PROVIDERS } from '@angular/http';
import { ROUTER_PROVIDERS } from '@angular/router';

bootstrap(AppComponent, [
    HTTP_PROVIDERS,
    ROUTER_PROVIDERS,
    provide(ExceptionHandler, {useClass: ErrorHandler})
]);

为什么我收到此错误?在ExceptionHandler实例化时,路由器是否可注入?

完整的源代码可在此处获取

https://github.com/harindaka/angular2-seed-typescript/tree/b368315ce6608085f3154a03bc53f0404ce16495

6 个答案:

答案 0 :(得分:4)

请参阅:ErrorHandler课程。您也可以添加Injectable装饰器以实现DI!



import { ErrorHandler, Injectable } from '@angular/core';

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {

  private myService: MyService;

  constructor(private injector: Injector) {
     this.myService = injector.get(MyService);
  }

  handleError(error) {
    alert('Bad things happening');
  }
  
}

@NgModule({
  providers: [
    {
      provide: ErrorHandler, 
      useClass: GlobalErrorHandler
    }
  ]
})
export class AppModule { }




注意:以上答案使用ExceptionHandler,在最终版本中删除了ErrorHandler

答案 1 :(得分:3)

更新 Presenter已重命名为ExceptionHandler https://stackoverflow.com/a/35239028/217408

<强> orgiginal

我猜这是由循环依赖引起的。您可以通过注入注入器并强制获取路由器来解决此问题:

ErrorHandler

答案 2 :(得分:3)

可能迟到了派对,但这对我有用(Angular 2 RC4):

import { Injectable, Injector, ExceptionHandler }    from '@angular/core';
import { Router } from '@angular/router';

@Injectable()
export class AppExceptionHandler extends ExceptionHandler {

    private router;
    injector: Injector;

    constructor(injector: Injector) {
        super(null, null);
        this.injector = injector;
    }

    call(exception: any, stackTrace?: any, reason?: string): void {
        if (this.router == null) {
            this.router = this.injector.get(Router);
        }

        // do something with the error such as spitting out to console:
        console.log('exception:', exception);
        console.log('stackTrace:', stackTrace);
        console.log('reason:', reason);

        // navigate to custom error page (defined in your routes)
        this.router.navigate(['error']);
    }
}

然后在你的main.ts中:

bootstrap(AppComponent, [
    HTTP_PROVIDERS,
    APP_ROUTER_PROVIDERS,
    provide(ExceptionHandler, { useClass: AppExceptionHandler })]
)

答案 3 :(得分:0)

这是一个非常简单的 - 要注入课程,你需要创建课程injectable。听起来很熟悉吧?

如果您在@Injectable()课程的顶部添加了ErrorHandler,则应该有效。

import { ExceptionHandler, Injectable } from '@angular/core';
import { Router } from '@angular/router';

@Injectable()
export class ErrorHandler extends ExceptionHandler{
    [...]
}

答案 4 :(得分:0)

刚出现类似的问题并像这样解决了(在app模块的providers数组中使用它):

{
  provide: ExceptionHandler,
    useFactory: (router) => {
      return new ErrorHandler(router);
    },
  deps: [Router]
}

答案 5 :(得分:0)

所以今天我遇到了类似的事情。我的情况有点不同,我扩展了Http,需要Router。但是,ErrorHandler也需要Http。使用上面的方法与Factories,我想我可以将Http注入ErrorHandler。我发现当ErrorHandler在Http的构造函数中调用依赖注入时,Router不存在(也没有其他所有必需的上下文)。

所以我让注入器在函数调用期间给我一个实例,而不是在构造函数中。当注射器实际上试图获得Http(在调用中)时,它已经在适当的上下文中创建。

CustomErrorHandler.ts:

import { ErrorHandler, Injector } from '@angular/core';
import { Http } from '@angular/http';
import { environment } from 'environments/environment';

export class CustomErrorHandler extends ErrorHandler {
  private http: Http;
  constructor(private injector: Injector) {
    super();
    // Calling this.injector.get(Http); here resulted in a null Router

    window.onerror = (msg: any, url: any, line: any, col: any, error: any) => {
      this.handleError(msg);
      return true;
    };
  }

  public handleError(error: any): void {
    try {
      // calling the injector here gave the application the time to build the correct context for the dependency injection that Http needed.
      if (!this.http) {
        this.http = this.injector.get(Http);
      }
      if (!error) {
        error = 'Unknown Error';
      }
      console.error(error);
      this.http.post('logtoserver/LogError', { Message: error.message, StackTrace: error.stack });
    } catch (exception) {
      // ignore
    }
  }
}

CustomHttpService.ts中的相关部分:

@Injectable()
export class CustomHttpService extends Http {

  constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private router: Router, private injector: Injector) {
    super(backend, defaultOptions);
  }

  request(urlOrRequest: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    // We needed Router here to call this.router.navigate(['...']);
    // ...
  }
}

app.module.ts:

import { NgModule, ErrorHandler, Injector } from '@angular/core';
import { Http, RequestOptions, XHRBackend } from '@angular/http';
import { CustomErrorHandler } from 'app/customErrorHandler';
// ...

export function customHttpServiceFactory(xhrBackend, requestOptions, router, injector) {
  return new CustomHttpService(xhrBackend, requestOptions, router, injector);
}

export function customErrorHandler(injector) {
    return new CustomErrorHandler(injector);
}

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
    { provide: Http, useFactory: customHttpServiceFactory, deps: [XHRBackend, RequestOptions, Router, Injector] },
    // { provide: UrlSerializer, useClass: LowercaseUrlSerializer },
    { provide: ErrorHandler, useFactory: customErrorHandler, deps: [Injector] },
    ...
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}