refactor(core): fix bootstrapModule regarding zones and initializers (#10383)

This makes `bootstrapModuleFactory` wait for promises
returned by `APP_INITIALIZER`s, also making `bootstrapModuleFactory` async.
I.e. now `bootstrapModule` and `bootstrapModuleFactory` behave in the
same way.

This ensures that all code from module instantiation, to creating
`ApplicationRef`s as well as calling `APP_INITIALIZERS` is run
in the Angular zone.

This also moves the invocation of the initializers from the `ApplicationRef`
constructor into the `bootstrapModuleFactory` call, allowing initializers
to get a hold of `ApplicationRef` (see #9101).

Fixes #9101
Fixes #10363
Fixes #10205
This commit is contained in:
Tobias Bosch
2016-07-29 06:47:40 -07:00
parent 633c7d1ebe
commit a46437c57d
9 changed files with 223 additions and 211 deletions

View File

@ -54,19 +54,10 @@ export function rootRoute(router: Router): ActivatedRoute {
return router.routerState.root;
}
export function setupRouterInitializer(injector: Injector) {
// https://github.com/angular/angular/issues/9101
// Delay the router instantiation to avoid circular dependency (ApplicationRef ->
// APP_INITIALIZER -> Router)
setTimeout(() => {
const appRef = injector.get(ApplicationRef);
if (appRef.componentTypes.length == 0) {
appRef.registerBootstrapListener(() => { injector.get(Router).initialNavigation(); });
} else {
injector.get(Router).initialNavigation();
}
}, 0);
return (): any => null;
export function setupRouterInitializer(injector: Injector, appRef: ApplicationRef) {
return () => {
appRef.registerBootstrapListener(() => { injector.get(Router).initialNavigation(); });
};
}
/**

View File

@ -76,18 +76,11 @@ export const ROUTER_PROVIDERS: any[] = [
*/
@NgModule({declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES})
export class RouterModule {
constructor(private injector: Injector) {
constructor(private injector: Injector, appRef: ApplicationRef) {
// do the initialization only once
if ((<any>injector).parent.get(RouterModule, null)) return;
setTimeout(() => {
const appRef = injector.get(ApplicationRef);
if (appRef.componentTypes.length == 0) {
appRef.registerBootstrapListener(() => { injector.get(Router).initialNavigation(); });
} else {
injector.get(Router).initialNavigation();
}
}, 0);
appRef.registerBootstrapListener(() => { injector.get(Router).initialNavigation(); });
}
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders {