Angular - навигация в ErrorHandler работает только с zone.run()

Я реализовал глобальный обработчик ошибок в 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 ответа

Решение

Я обнаружил проблему самостоятельно после удаления всех сервисов и модулей из моего приложения и добавления их обратно один за другим, пока маршрутизация не сломалась снова. Модуль BrowserAnimationsModule вызывает проблему.

Есть также открытый вопрос на GitHub => https://github.com/angular/angular/issues/20290

Ошибки в обработчиках ошибок находятся вне угловой зоны.

например:

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

По этой причине это нормально, когда навигацию приходится заключать в ngZone.run()Если вы этого не сделаете, angular не обнаружит изменения, и вы получите глючную навигацию и/или неотвечающие страницы.

То, что я сделал, чтобы обойти это, чтобы позвонить window.open(url);

Я думаю, что ваш роутер не работает, потому что, когда приложение Angular дает сбой, кажется, больше ничего не работает. По крайней мере, это мой опыт с этим.

Ваш LoggingService, чтобы избежать создания циклической зависимости, также должен быть в вашем массиве провайдеров в app.module.ts.

У меня есть что-то вроде этого:

providers: [
    CrashReportService,
    { provide: ErrorHandler, useClass: MyErrorHandler},
  ],
Другие вопросы по тегам