[译] 监听 Angular 启动过程

news/2024/7/3 12:58:41 标签: javascript
原文链接: Hooking into the Angular bootstrap process

Angular 提供了一些机制来监听框架初始化过程,本文主要探索如何使用这些机制。

APP_BOOTSTRAP_LISTENER

可以为 APP_BOOTSTRAP_LISTENER 令牌注册监听器来监听 Angular 启动过程,比如看看 Angular 源码 里是如何使用的:

private _loadComponent(componentRef: ComponentRef<any>): void {
    this.attachView(componentRef.hostView);
    this.tick();
    this.components.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));
  }

这个 _loadComponent() 函数会在初始化程序时被调用(译者注:这句可参考 application_ref.tsL245L281L463L492),通过观察这个函数不仅知道一个组件是如何被添加到程序里的(译者注:该方法第三行),还能知道对于每一个启动组件,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 {
}

在运行完上面代码后,我又查阅了官方文档,文档上是这样描述的(译者注:为清晰理解,该描述不翻译):

All callbacks provided via this token will be called for every component that is bootstrapped. Signature of the callback:
(componentRef: ComponentRef) => void

APP_INITIALIZER

Angular 也在程序(application)初始化前提供了钩子机制(译者注:Angular 框架有 platform 和 application 概念,Angular 在启动时会先实例化 platform,然后是 application,一个 platform 可以有多个 application,而 platform 可以有 platform-browser、platform-service-worker 或者 platform-server,因为 Angular 框架想做到跨平台,所以它得根据当前运行环境实例化特定的 platform。关于 platform 和 application 实例化过程也可参考 如何手动启动 Angular 程序),然后在初始化后就是变更检测和模板渲染过程。这段初始化过程步骤 是(译者注:下面源码是在 L53):

if (this.appInits) {
     for (let i = 0; i < this.appInits.length; i++) {
       const initResult = this.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 ,并通过该对象拿到 ApplicationRefComponentRef


http://www.niftyadmin.cn/n/992151.html

相关文章

ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务

在安装ORACLE 11G 过程中由于配置的原因&#xff0c;安装过程中报了如下错误&#xff1a;按照安装提示执行后面的操作后&#xff0c;打开PL/SQL DEVELOPER 连接数据库时总报ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务!ORACLE NET MANAGER里面测试&#xff0c…

jsp中生成的验证码和存在session里面的验证码不一致的处理

今天在调试项目的时候发现&#xff0c;在提交表单的时候的验证码有问题&#xff0c;问题是这样的&#xff1a;就是通过debug模式查看得知&#xff1a;jsp页面生成的验证码和表单输入的页面输入的一样&#xff0c;但是到后台执行的时候&#xff0c;你会发现他们是不一样的&#…

springBoot系列之五-----JSON

目录 jackson GSON FastJson jackson springBoot项目中如何往前端返回JSON数据&#xff0c;详解 其实说springBoot呢不如说是springMVC返回json,因为springBoot和springMVC时一脉相承的。 一般springBoot web项目需要引入pom依赖&#xff1a; <dependency><gr…

在Ubuntu上配置使用memcached及PHP Memecache 客户端(apt-get方式)

memcache是一个高性能的分布式的内存对象缓存系统&#xff0c;通过在内存里维护一个统一的巨大的hash表&#xff0c;它能够用来存储各种格式的数据&#xff0c;包括图像、视 频、文件以及数据库检索的结果等。 要开发使用memcache &#xff0c;我们必须安装memcache服务端和PHP…

每日一题20180401-Linux

为什么80%的码农都做不了架构师&#xff1f;>>> 一、题目 1.1 在mysql命令行临时开启自动补全 1.2 通过shell脚本打印乘法口诀表 二、答案 2.1 # auto-rehash&#xff1a;读取表信息和列信息&#xff0c;可以在连上终端后开启tab补齐功能# 进入mysql命令行时指定 m…

实时流Streaming大数据:Storm,Spark和Samza

当前有许多分布式计算系统能够实时处理大数据&#xff0c;这篇文章是对Apache的三个框架进行比较&#xff0c;试图提供一个快速的高屋建瓴地异同性总结。 Apache Storm 在Storm中&#xff0c;你设计的实时计算图称为toplogy&#xff0c;将其以集群方式运行&#xff0c;其主节点…

如何用简单易懂的例子解释隐马尔可夫模型?

隐马尔可夫&#xff08;HMM&#xff09;好讲&#xff0c;简单易懂不好讲。 本文回答简单易懂&#xff0c;https://www.zhihu.com/question/20962240/answer/33438846转载于:https://www.cnblogs.com/liuyihai/p/8449068.html

springBoot系列之六----静态资源

一般创建项目时默认在resources 目录下 自动创建一个static存放静态文件的文件夹 springBoot默认的静态资源路径一共有四种。 /*** Properties used to configure resource handling.** author Phillip Webb* author Brian Clozel* author Dave Syer* author Venil Noronha* …