Angular - ErrorHandler 中的导航仅适用于 zone.run()
Angular - Navigation in ErrorHandler only works with 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 也没有被调用。
如果我必须使用这样的 "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() {
}
}
我为解决这个问题所做的事情是调用 window.open(url);
我认为您的路由器无法正常工作,因为当 Angular 应用程序崩溃时,似乎一切都无法正常工作。至少这是我的经验。
为了避免产生循环依赖,您的 LoggingService 也应该在 app.module.ts 中的 providers 数组中。
我有这样的东西:
providers: [
CrashReportService,
{ provide: ErrorHandler, useClass: MyErrorHandler},
],
在从我的应用程序中删除每个服务和模块并将它们一一添加回来直到路由再次中断后,我自己发现了这个问题。模块 BrowserAnimationsModule 导致了问题。
GitHub 上还有一个未解决的问题 => https://github.com/angular/angular/issues/20290
错误处理程序中的错误超出 angular 区域。
例如:
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error) {
NgZone.assertInAngularZone(); // This will throw an error
}
}
出于这个原因,必须将导航包装到 ngZone.run()
中是正常的,如果您不这样做,angular 将不会检测到更改,您最终会遇到错误导航和/或无响应的页面。
我在 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() {
}
}
我为解决这个问题所做的事情是调用 window.open(url);
我认为您的路由器无法正常工作,因为当 Angular 应用程序崩溃时,似乎一切都无法正常工作。至少这是我的经验。
为了避免产生循环依赖,您的 LoggingService 也应该在 app.module.ts 中的 providers 数组中。
我有这样的东西:
providers: [
CrashReportService,
{ provide: ErrorHandler, useClass: MyErrorHandler},
],
在从我的应用程序中删除每个服务和模块并将它们一一添加回来直到路由再次中断后,我自己发现了这个问题。模块 BrowserAnimationsModule 导致了问题。
GitHub 上还有一个未解决的问题 => https://github.com/angular/angular/issues/20290
错误处理程序中的错误超出 angular 区域。
例如:
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error) {
NgZone.assertInAngularZone(); // This will throw an error
}
}
出于这个原因,必须将导航包装到 ngZone.run()
中是正常的,如果您不这样做,angular 将不会检测到更改,您最终会遇到错误导航和/或无响应的页面。