Angular 4 + zonejs: маршрутизация перестает работать после ошибки uncaught

Если во время маршрутизации происходит ошибка от компонента (конструктора или ngOnInit), навигация больше не будет работать.

Это происходит, даже если есть глобальный ErrorHandler и ErrorHandler для RouterModule, добавлен ZoneListener, чтобы быть уверенным, а также - см. Приложение.модуль.ТС

минимальный пример: https://embed.plnkr.co/L19S3hKWyqgKUIT1EJlI/preview

обязательно откройте консоль. После того как вы нажали "Пример компонента" есть некоторые stacktraces в результате вынужденной ошибки в ExampleFormComponent. После этого вы не сможете вернуться в "дом".

как обрабатывать неожиданные, необнаруженные ошибки, чтобы убедиться, что они не сломать все приложение?

1 ответов


Я бы сделал некоторые обходные пути, как:

let hasRouterError = false;
@Injectable()
export class MyErrorHandler implements ErrorHandler {
  constructor(private inj: Injector) {}

  handleError(error: any): void {
    console.log('MyErrorHandler: ' + error);

    if(hasRouterError) {
      let router = this.inj.get(Router);
      router.navigated = false;
    }

    //throw error; // it is necessarily otherwise handleError won't be executed during next error
  }
}

export function MyRouterErrorHandler(error: any) {
  console.log('RouterErrorHandler: ' + error);
  hasRouterError = true;
  throw error;
}

и мы должны использовать custom RouteReuseStrategy:

export class PreventErrorRouteReuseStrategy implements RouteReuseStrategy {
  shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
  store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
  shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null { return null; }
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    if(hasRouterError) {
      hasRouterError = false;
      return false;
    }
    return future.routeConfig === curr.routeConfig;
  }
}

отличается от DefaultRouteReuseStrategy только один этот код

if(hasRouterError) {
  hasRouterError = false;
  return false;
}

не забудьте добавить его в массив провайдеры:

import { RouteReuseStrategy } from '@angular/router';
...
{ provide: RouteReuseStrategy, useClass: PreventErrorRouteReuseStrategy },

вы можете попробовать его в Изменен Plunker