乐趣区

关于前端:从编译后的代码分析-Angular-Injectable-的工作原理

在开始本文的探讨之前,让咱们先做一道多选题:

上面对于 @Injectable 的形容,哪些是正确的?

A @Injectable 装璜器应该增加到每个服务中。
B @Injectable 装璜器应该增加到任何应用依赖注入 (DI) 的服务中。
C 如果您不应用“providedIn”选项,则不须要增加 @Injectable 装璜器。
D @Injectable 装璜器与“providedIn”选项一起,意味着不应将服务增加到模块的提供者数组中。

答案是 B 和 D.

Angular 带有本人的 DI 框架,并用于 Angular 应用程序的设计以加强其模块化和效率。@Injectable() 是任何 Angular 服务定义的重要组成部分。有些人可能抉择谬误答案的起因是他们谬误地判断了 @Injectable 装璜器和 Angular 中的 DI 之间的关系,不理解这个装璜器的真正作用。

Adding @Injectable Is Not Registering the Service

对于用于 DI 的管制反转 (IOC) 容器,有两个成对的知识点须要把握。首先是令牌。要向 IOC 容器注册某些服务,须要一个令牌。令牌是注册任何服务的惟一标识符。第二个知识点是 provider.

提供者帮忙 DI 容器创立特定依赖项的实例。

在 Angular 中,应用令牌注册服务并将其传递给提供者能够通过两种不同的形式实现。

首先,能够应用特定的 @NgModule 注册服务。该过程是通过将服务传递给提供者数组 providers 来进行注册。在上面这个例子里,应用的令牌是 typescript 类型 MyService。这里的提供者是 useClass。这个提供者策略,告诉 Angular 框架,能够通过 new 关键字来启动某个依赖项的实例。

@NgModule({
  ...
  providers: [
    // long hand syntax
      {provide: MyService, useClass: MyService},
      // short hand syntax
      MyService
  ],
})

第二种形式是应用 @Injectable

@Injectable({providedIn: 'root'})
export class MyService {constructor() {}}

这里要留神辨别的一点是,@Injectable 装璜器与向容器注册服务无关。那么 @Injectable 装璜器的目标是什么?

事实上,MyService 能够有一些依赖项是规范的。例如,您能够应用 HttpClient。

import {HttpClient} from '@angular/common/http';

@Injectable()
export class MyService {constructor(private httpClient: HttpClient) {}}

让咱们尝试理解当您须要获取 MyService 实例时会产生什么。当 Angular 须要创立服务时,它应该传递一个 HttpClient 的实例。那么它怎么能做到呢?

首先,Angular 应该晓得提到了哪个依赖项。还记得您应用令牌来注册依赖项吗?出于同样的起因,您能够向 Angular 申请该依赖项的一个实例。因而,Angular 将考察构造函数并查看是否为令牌 HttpClient 申请了服务。如果应用该令牌注册了服务,Angular 能够应用该令牌启动 MyService 并提供它创立的实例。

上面是编译后的 JavaScript 代码:

var MyService = /** @class */ (function () {function MyService(httpClient) {this.httpClient = httpClient;}
    MyService = __decorate([Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"])(),
        __metadata(
            "design:paramtypes", 
            [_angular_common_http__WEBPACK_IMPORTED_MODULE_1__["HttpClient"]]
        )
    ], MyService);
    return MyService;
}());
退出移动版