Angular 4 + zonejs: routing stops working after an uncaught error

If during routing there is an uncaught error from the component (constructor or ngOnInit), navigation will no longer work.

This happens even if there is a global ErrorHandler and ErrorHandler for the RouterModule, a ZoneListener has been added, and also see app.module.ts

Minimum example: https://embed.plnkr.co/L19S3hKWyqgKUIT1EJlI/preview

Be sure to open the console. After you clicked “Example Component”, as a result of a forced error, there are several stacks in ExampleFormComponent. After that, you will not be able to return to the "Home".

How to handle unexpected, incomprehensible errors to make sure that they do not break the entire application?

+6
source share
1 answer

I would make some workaround like:

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;
}

and we should use 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;
  }
}

It differs from DefaultRouteReuseStrategyjust this one code.

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

don't forget to add it to the providers array:

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

You can try it in Modified Plunker

+2
source

Source: https://habr.com/ru/post/1017108/


All Articles