从编译后的代码,分析 Angular @Injectable 的工作原理

举报
汪子熙 发表于 2022/12/12 11:25:55 2022/12/12
【摘要】 在开始本文的讨论之前,让我们先做一道多选题:下面对于 @Injectable 的描述,哪些是正确的?A @Injectable 装饰器应该添加到每个服务中。B @Injectable 装饰器应该添加到任何使用依赖注入 (DI) 的服务中。C 如果您不使用“providedIn”选项,则不需要添加 @Injectable 装饰器。D @Injectable 装饰器与“providedIn”选项...

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

下面对于 @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;
}());
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。