2

我为所有未处理的异常在 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 也没有被调用。

如果我必须使用这样的“hack”来让我的路由对我有用,那么我的应用程序中的某个地方似乎配置错​​误。

有人知道我需要改变什么才能让它在没有区域调用的情况下运行吗?


我的路由:

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

4 回答 4

3

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

例如:

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

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

于 2021-03-12T14:54:59.483 回答
1

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

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

于 2018-02-14T14:44:50.467 回答
-1

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

我有这样的事情:

providers: [
    CrashReportService,
    { provide: ErrorHandler, useClass: MyErrorHandler},
  ],
于 2018-02-14T13:11:50.807 回答
-2

我为解决这个问题所做的事情就是打电话window.open(url);

我认为您的路由器不起作用,因为当 Angular 应用程序崩溃时,似乎什么都不起作用了。至少这是我的经验。

于 2018-02-14T12:56:31.750 回答