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},
],