AngularInDepth уходит от Medium. Эта статья, ее обновления и более свежие статьи размещены на новой платформе inDepth.dev
Angular предоставляет несколько механизмов для подключения к процессу инициализации. В этой статье они исследуются и показано, как их можно использовать.
APP_BOOTSTRAP_LISTENER
Можно зарегистрировать слушателей для процесса начальной загрузки Angular. Вот код, где они называются:
private _loadComponent(componentRef: ComponentRef<any>): void { this.attachView(componentRef.hostView); this.tick(); this._rootComponents.push(componentRef); // Get the listeners lazily to prevent DI cycles. const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners); listeners.forEach((listener) => listener(componentRef)); }
Это функция, которую Angular вызывает при создании экземпляра приложения. Помимо понимания того, как компонент добавляется в приложение, он также предполагает, что для каждого загружаемого компонента Angular вызывает прослушиватели, зарегистрированные под токеном APP_BOOTSTRAP_LISTENER
, и передает им загруженный компонент.
Это означает, что мы можем использовать такие хуки, чтобы подписаться на процесс начальной загрузки приложения и выполнить нашу логику инициализации. Например, вот как Router
подключается к процессу и выполняет некоторую инициализацию.
Поскольку Angular передает инициализированный компонент в обратный вызов, мы можем получить корневой компонент ComponentRef приложения следующим образом:
import {APP_BOOTSTRAP_LISTENER, ...} from '@angular/core'; @NgModule({ imports: [BrowserModule, ReactiveFormsModule, TasksModule], declarations: [AppComponent, BComponent, AComponent, SComponent, LiteralsComponent], providers: [{ provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: () => { return (component: ComponentRef<any>) => { console.log(component.instance.title); } } }], bootstrap: [AppComponent] }) export class AppModule { }
После того, как я столкнулся с такой функциональностью в источниках, я проверил документацию, она описана как экспериментальная и приводится следующее описание:
Все обратные вызовы, предоставленные с помощью этого токена, будут вызываться для каждого загружаемого компонента. Подпись обратного звонка:
(componentRef: ComponentRef) => void
APP_INITIALIZER
Angular также предоставляет механизм для выполнения некоторой логики инициализации, прежде чем он объявит приложение как инициализированное и продолжит обнаружение изменений и отрисовку шаблона. Вот где происходит инициализация:
constructor(@Inject(APP_INITIALIZER) @Optional() appInits: (() => any)[]) { const asyncInitPromises: Promise<any>[] = []; if (appInits) { for (let i = 0; i < appInits.length; i++) { const initResult = appInits[i](); if (isPromise(initResult)) { asyncInitPromises.push(initResult); } } }
Итак, так же, как мы сделали это для токена APP_BOOTSTRAP_LISTENER
, мы просто определяем поставщика APP_INITIALIZER
, и наша функция будет вызвана. В следующем примере инициализация Angular задерживается на 5 секунд:
{ provide: APP_INITIALIZER, useFactory: () => { return () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, 5000); }); } }, multi: true }
И вы можете определить несколько APP_INITIALIZER’
следующим образом:
{ provide: APP_INITIALIZER, useFactory: () => { return () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, 5000); }); } }, multi: true }, { provide: APP_INITIALIZER, useFactory: () => { return () => { return new Promise.resolve(2); } }, multi: true }
BootstrapModule
Еще один момент, когда вы можете подключиться к процессу начальной загрузки приложения, - это bootstrapModule
метод:
platform.bootstrapModule(AppModule).then((module) => {
let applicationRef = module.injector.get(ApplicationRef);
let rootComponentRef = applicationRef.components[0];
});
Здесь вы можете получить NgModuleRef для модуля начальной загрузки, через который вы можете получить доступ к ApplicationRef и ComponentRef.