Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Notify on Angular 2 app initialization error

An uncaught exception (injector or just random error) in any component during bootstrap may lead to bootstrap failure.

Due to browser incompatibility the app may not start bootstrap process at all.

I'm looking for a way to notify a user (with alert, modal, etc) on critical error that happened during Angular 2 app initialization, so a user could be sure that the app not just loads forever but failed for some reason.

What's the good recipe to handle this case in Angular 2?

like image 299
Estus Flask Avatar asked Nov 02 '16 21:11

Estus Flask


2 Answers

PlatformRef.bootstrapModule return's a promise where we can .catch the error, while bootstrap(initializing) the app.

platformBrowserDynamic().bootstrapModule(<AppName>)
    .catch(er‌​r => console.error(err));

There was a bug, which was just resolved(changelog). Thanks to @estus, for pointing it out.

like image 103
Bhavik Avatar answered Nov 06 '22 14:11

Bhavik


It was possible to fix this with altered deferred pattern. However, the solution is based on the assumption that bootstrapping is synchronous and happens within one tick, which may be wrong.

Still not sure if there are better approaches.

class InitDeferred {
  promise: Promise<any>;
  private fulfilled: boolean;

  constructor() {
    this.promise = new Promise((resolve, reject) => {
      setTimeout(() => this.fulfilled === true ? resolve() : reject('init error'));
    });
  }

  resolve() {
    this.fulfilled = true;
  }

  reject() {
    this.fulfilled = false;
  }
}

const initDeferred = new InitDeferred;
export default initDeferred;

@Injectable()
export class InitErrorHandler extends ErrorHandler {
    handleError(error: any): void {
      initDeferred.reject();
      super.handleError(error);
    }
}

@Component(...)
export class App extends OnInit {
  ngOnInit() {
    initDeferred.resolve();
  }
}

@NgModule({
  ...
  providers: [{ provide: ErrorHandler, useClass: InitErrorHandler }]
})
export class AppModule {}

initDeferred.promise.catch(alert);
platformBrowserDynamic().bootstrapModule(AppModule);
like image 42
Estus Flask Avatar answered Nov 06 '22 12:11

Estus Flask