Estus Flask
Estus Flask

Reputation: 223268

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?

Upvotes: 20

Views: 6119

Answers (2)

Bhavik
Bhavik

Reputation: 4904

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.

Upvotes: 4

Estus Flask
Estus Flask

Reputation: 223268

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

Upvotes: 2

Related Questions