Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Application becomes unresponsive after encountering an exception

Tags:

angular

How to tell Angular 2 to not block the whole application when it encounters an exception?

I'm not sure if it's even possible, because Google didn't enlighten me on this. But it seems critical to any single page web application.

Whenever Angular 2 encounters an exception and throws an error, the complete application becomes unresponsive.

I know that in JavaScript

try {
  doSomething();
}
catch(err) {
  handleErrors(err);
}

might solve the problem.

But I just want to know if there is any Angular specific solution or workaround?

like image 426
Ankit Singh Avatar asked Feb 06 '16 07:02

Ankit Singh


4 Answers

On angular 2 final version, you can implement custom ErrorHandler (Angular 2 docs example):

import {NgModule, ErrorHandler} from '@angular/core';

class MyErrorHandler implements ErrorHandler {
  handleError(error) {
    // do something with the exception
  }
}

@NgModule({
  providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
})
class MyModule {}
like image 160
Asaf Hananel Avatar answered Nov 17 '22 22:11

Asaf Hananel


UPDATE:

2.0.0 RC.6 changed the name from ExceptionHandler to ErrorHandler and call to handleError:

@Injectable()
class MyErrorHandler implements ErrorHandler {

  handleError(error) {
    // do something with the exception
  }
}


@NgModule({
  directives: [MyApp],
  providers: [
    {provide: ErrorHandler, useClass: MyErrorHandler}
  ]
})
export class AppModule {}

See also this.

ORIGINAL:

Implement a custom exception handler:

@Injectable()
class MyExceptionHandler implements ExceptionHandler {
  call(error, stackTrace = null, reason = null) {
    // do something with the exception
  }
}


@NgModule({
  directives: [MyApp],
  providers: [
    {provide: ExceptionHandler, useClass: MyExceptionHandler}
  ]
})
export class AppModule {}

See also this and this.

I haven't tried myself if this allows the application to continue after an exception, but I think it's worth a try. At least reloading the page automatically should be possible.

Generally, an exception should be handled as close as possible to the cause when there is a way to recover.

like image 25
Günter Zöchbauer Avatar answered Nov 17 '22 23:11

Günter Zöchbauer


I tried to implement Custom Exception Handler as directed by @GünterZöchbauer

and this worked for me


Bootstrap your application with CustomExceptionHandler.

import {ExceptionHandler} from 'angular2/core';

class _ArrayLogger {
  res = [];

  log(s:any):void {
    this.res.push(s);
  }
  logError(s:any):void {
    this.res.push(s);
  }
  logGroup(s:any):void {
    this.res.push(s);
  }
  logGroupEnd() {
    if(this.res.length) {

      //this section executes if any error is logged by angular. 

      //do your stuff here

      /*e.g

        if(location.pathname !== 'dashboard') {
           window.location.href = '/dashboard'; // condition is required to prevent infinite loop
        }

        */
     }
  };
}

export class CustomExceptionHandler extends ExceptionHandler {
  constructor() {
    super(new _ArrayLogger(), true);
  }

  call(error, stackTrace = null, reason = null) {
    super.call(error, stackTrace, reason);
  }
}

bootstrap(MyApp, [provide(ExceptionHandler, {useClass: CustomExceptionHandler})])
like image 3
Ankit Singh Avatar answered Nov 17 '22 22:11

Ankit Singh


I think the issue might occur when you're using RxJS Observables, which unsubscribe when they encounter any error. If that's the case for you, you might need to:

  1. Catch the exception within the .subscribe's onNext handler with try...catch instead of inside onError handler.
  2. Re-subscribe in .subscribe's onError handler.
like image 2
Michal Leszczyk Avatar answered Nov 17 '22 23:11

Michal Leszczyk