Angular - ErrorHandler中的导航仅适用于zone.run()

时间:2018-02-14 12:49:18

标签: angular angular-router angular-errorhandler

我在angular(版本5.2.0)中为所有未处理的异常实现了一个全局错误处理程序。

全局错误处理程序如下所示:

import { Router } from '@angular/router';
import { ErrorHandler, Injectable, Injector, NgZone } from '@angular/core';
import { LoggingService } from '../services/logging.service';

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {

  private router: Router;

  constructor(injector: Injector, private zone: NgZone, private loggingService: LoggingService) {
    setTimeout(() => {
      this.router = injector.get(Router);
    });
  }

  handleError(error) {
    this.loggingService.logErrorToApi(error);
    this.zone.run(() => this.router.navigate(['/error']));
  }
}

只有拨打电话this.zone.run(...)时,路由才有效。 如果我删除此调用,则路由仅将路由error添加到URL,并且不显示该组件。也没有调用ngOnInit。

如果我必须使用这样的“黑客”让我的路由工作给我,似乎我的应用程序中的某处有错误的配置。

有没有人知道我需要改变什么来让它在没有区域呼叫的情况下运行?

我的路线:

const appRoutes: Routes = [
  {
    path: 'error',
    component: ErrorComponent
  },
  {
    path: '',
    component: HomeComponent,
    canActivate: [CookieGuard]
  },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    FooterComponent,
    HomeComponent,
    PageNotFoundComponent,
    ErrorComponent
  ],
  imports: [
    RouterModule.forRoot(appRoutes, { enableTracing: !environment.production }),
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    HttpClientXsrfModule,
  ],
  providers: [
    { provide: ErrorHandler, useClass: GlobalErrorHandler },
    ApiHttpClientService,
    AppSettingsService,
    CookieGuard,
    LoggingService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

这是我调用的错误组件:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'error',
  templateUrl: './error.component.html',
  styleUrls: ['./error.component.scss']
})
export class ErrorComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }
}

4 个答案:

答案 0 :(得分:2)

错误处理程序中的错误超出了角度区域。

例如:

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  handleError(error) {
     NgZone.assertInAngularZone(); // This will throw an error
  }
}

出于这个原因,必须将导航包装到 ngZone.run() 中是正常的,如果您不这样做,angular 将无法检测到更改,您最终会得到有问题的导航和/或无响应的页面.

答案 1 :(得分:0)

我从我的应用程序中删除每个服务和模块并逐个添加它们直到路由再次中断后,我自己发现了这个问题。模块 BrowserAnimationsModule 会导致问题。

GitHub上还有一个未解决的问题=> https://github.com/angular/angular/issues/20290

答案 2 :(得分:-1)

为避免创建循环依赖项,您的LoggingService也应位于app.module.ts中的providers数组中。

我有这样的事情:

providers: [
    CrashReportService,
    { provide: ErrorHandler, useClass: MyErrorHandler},
  ],

答案 3 :(得分:-2)

我做的事情是打电话给window.open(url);

我认为你的路由器不起作用,因为当Angular应用程序崩溃时,似乎没有任何东西可以工作了。至少这是我的经验。