关于 Angular 注解 @Injectable() 使用的一些误区

举报
汪子熙 发表于 2022/12/11 10:38:51 2022/12/11
【摘要】 当使用 Angular 装饰器时,被装饰的类以 Angular 可以读取的格式存储关于自身的元数据——这包括关于它需要获取和注入哪些依赖项的元数据。 如果一个类上没有使用 Angular 装饰器,那么 Angular 就无法读取它需要的依赖项。 这就是我们需要使用@Injectable() 的原因。 如果我们的服务注入提供者,我们必须添加 @Injectable().

一个常见的误解是,@Injectable() 是我们计划在应用程序中注入组件/服务的任何类的必需装饰器。 这种说法并不完全正确。

当使用 Angular 装饰器时,被装饰的类以 Angular 可以读取的格式存储关于自身的元数据——这包括关于它需要获取和注入哪些依赖项的元数据。

如果一个类上没有使用 Angular 装饰器,那么 Angular 就无法读取它需要的依赖项。 这就是我们需要使用@Injectable() 的原因。

如果我们的服务注入提供者,我们必须添加 @Injectable(),这个注解除了告诉 Angular 存储它需要的元数据之外,没有实现其他额外的功能。

假设我们有下面这个 Service class:

export class UserService {
  isAuthenticated(): boolean {
    return true;
  }
}

对于上面这个类,我们不需要用 @Injectable装饰它,以便能够将其注入到组件中。因为 UserService 本身不注入任何 providers.

然而如果我们的 Service 类本身又注入了其他的依赖:

import { Http } from '@angular/http';

export class UserService {
  constructor(private http: Http) {}
  isAuthenticated(): Observable<boolean> {
    return this.http.get('/api/user').map((res) => res.json());
  }
}

上面的代码无法正常工作,因为 Http 提供程序元数据不会被存储以供 Angular 正确组合。

解决方案就是使用 @Injectable 注解:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class UserService {
  constructor(private http: Http) {}
  isAuthenticated(): Observable<boolean> {
    return this.http.get('/api/user').map((res) => res.json());
  }
}

SAP Spartacus 的例子:

对于用于 DI 的控制反转 (IOC) 容器,开发人员通常需要完成两种设置。 首先是令牌。 要向 IOC 容器注册依赖,需要提供一个令牌。 令牌是注册任何服务的独一无二的标识符。 第二件事是配置 provider 本身。 提供者帮助 DI 容器创建特定依赖项的运行时实例。

在 Angular 中,使用令牌注册服务,并将其传递给提供者的具体方法如下所述:

首先,可以使用特定的@NgModule 注册服务。 该过程是通过将服务传递给提供者数组来进行注册。 下面是一个例子,使用的令牌是 typescript 类型 MyService. 这里的提供者是 useClass. 这个提供者策略,通知 Angular DI 框架,可以通过 new 关键字来实例化某个依赖项。

例子代码:

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

注意上面提供了两种语法,因为 provide 和 useClass 指向的 type 定义相同,所以可以直接简写成 MyService.

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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