angular 依赖注入

业界 作者:SegmentFault 2021-11-08 22:51:18

作者:weiewiyi

来源:SegmentFault 思否社区

前言

问题起因是因为在GriderService中忘记给根模块提供注入。
即没有写

@Injectable({
  providedIn: 'root'
})

手动注入

当时想着,能不能单纯在组件中使用provide GriderService使这个组件正常用service提供的服务.就像下面这样:

providers: [
        {
          provide: GriderService
        }
      ]


但这样还不行。
因为GriderService的函数中同样需要依赖注入HttpClient,如下

constructor(protected httpClient: HttpClient) { }


所以,手动注入GriderService需要先手动注入HttpClient

所以我尝试着手动注入了HttpClient。并且如果new一个HttpClient的话,需要先new一个HttpHandler,这是Httpclient的构造函数所需要的。或许我应该这么做:

let httpHandler = new HttpHandler();
   let httpClient = new HttpClient(httpHandler);


但是,实际上HttpHandler是抽象类,并不能被实例化。


最后也没查到什么可行性的代码。我们应该使用依赖注入。DI是 Angular 中的一个基本概念,也是使该框架如此有用的原因之一。

依赖注入


@Injectable() 装饰器标识服务类。该 providedIn 属性配置指定的 ModuleInjector,这里的 root 会把让该服务在 root ModuleInjector 上可用

优点

用 @Injectable() 的 providedIn 属性优于 @NgModule() 的 providers 数组,不仅在于它方便快捷,还因为使用 @Injectable() 的 providedIn 时,优化工具可以进行摇树优化(Tree Shaking)简单来说 经过Tree Shaking,不该留在代码中的多余代码,则会被摇掉

root

root 实际上是 AppModule 的别名,表示根模块,我们因此不需要额外导入 AppModule,所有的模块原则上都属于根模块的子模块,所以所有的子模块都可以无条件的使用root根模块上的资源

关于注射器

在 root ModuleInjector 之上还有两个注入器,一个是额外的 ModuleInjector,一个是 NullInjector()


为了理解这张图,先大致了解一下从angular启动。

angular启动

每一个 Angular 应用都以 main.ts 文件作为起点。(main.cs目前位于项目的src文件夹下,与app文件夹是同一级)


main.cs中最关键的是这两行代码:


1、platformBrowserDynamic() 方法创建一个由 PlatformModule 配置的注入器,简单来说就是浏览器平台的工厂函数,执行会返回浏览器平台的实例

2、bootstrapModule() 方法会创建一个由 AppModule 配置的注入器作为平台注入器子注入器也就是 root ModuleInjector

3、同时bootstrapModule启动app文件夹下的AppModule后,Angular 会去检查模块 AppModule 的 bootstrap 属性,该模块是用来启动程序的:

@NgModule({
  imports: [BrowserModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

依赖注入服务流程

大致理解了启动流程之后,我们再结合刚才那张图来看就很好理解了。


1.platformBrowserDynamic创建一个由 PlatformModule 配置的注入器Modele Injector。该注入器包含特定平台的依赖项

2.使用bootstrapModule方法,创建root ModeleInjector。

3.root ModeleInjector启动之后。若某个service可以给root提供服务,即
该service依赖注入root,root模块就可以使用该service提供的服务

图例


至于最顶层的NullInjector(),它是树的顶部。如果你在树中向上走了很远,以至于要在 NullInjector() 中寻找服务,那么除非使用 @Optional(),否则将收到错误消息,因为最终所有东西都将以 NullInjector() 结束并返回错误

总结:DI增加了angular应用程序的灵活性和模块化,它可以使得我们这样方便地使用

constructor(private http: HttpClient)


假如没有Angular DI机制,我们必须手动提供HttpClient来创建我们自己的服务。



点击左下角阅读原文,到 SegmentFault 思否社区 和文章作者展开更多互动和交流,扫描下方”二维码“或在“公众号后台回复“ 入群 ”即可加入我们的技术交流群,收获更多的技术文章~


- END -



关注公众号:拾黑(shiheibook)了解更多

赞助链接:

关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接