Angular中如何不创建独立服务,直接使用ODataService实现组件API请求
问题(翻译自英文)
我有一个需要发起API请求的组件,同时存在一个用于此类服务的抽象类ODataService,其构造函数代码如下:
export class ODataService<T> extends ApiService { constructor(http: HttpClient, api: string) { super(http, null); this.servicePath = `odata/${api}`; } }
该构造函数非空。我不想为单个组件的单个方法编写独立服务,因此考虑直接使用该抽象类为组件创建“一次性使用”的服务,尝试的实现代码如下:
@Component({ selector: 'my-component', templateUrl: './my.component.html', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: 'myService', useFactory: (http) => new ODataService<IModel>(http, 'endpoint'), deps: [HttpClient] }] }) export class MyComponent implements OnInit { @Input() entityId: string constructor(private myService: ODataService<IModel>) { super(); } }
但注入服务时出现错误:
This constructor was not compatible with Dependency Injection.
请问这种实现方式是否可行?
回答
这种实现思路完全可行,报错的核心原因是注入标识不匹配:你在组件的providers配置里用字符串'myService'作为服务的注入令牌,但组件构造函数里直接请求注入ODataService<IModel>类型,Angular的依赖注入系统找不到对应关联,才抛出构造函数不兼容的错误。
给你两种调整方案:
方案一:用泛型类作为注入令牌
直接把providers里的provide值改成ODataService<IModel>,和构造函数的注入类型保持一致:
@Component({ selector: 'my-component', templateUrl: './my.component.html', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: ODataService<IModel>, useFactory: (http) => new ODataService<IModel>(http, 'endpoint'), deps: [HttpClient] }] }) export class MyComponent implements OnInit { @Input() entityId: string constructor(private myService: ODataService<IModel>) { // 注意:如果组件没有继承其他Angular组件类,这里的super()要删掉,否则会报错 } }
方案二:保留字符串令牌,用@Inject指定
如果想继续用'myService'作为标识,需要在构造函数里用@Inject()装饰器明确指定注入令牌:
import { Inject } from '@angular/core'; @Component({ selector: 'my-component', templateUrl: './my.component.html', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: 'myService', useFactory: (http) => new ODataService<IModel>(http, 'endpoint'), deps: [HttpClient] }] }) export class MyComponent implements OnInit { @Input() entityId: string constructor(@Inject('myService') private myService: ODataService<IModel>) { } }
额外提醒
- 你提到
ODataService是抽象类,但给出的代码里它是可实例化的普通泛型类(没有abstract关键字),如果它确实是抽象类,要确保实例化时所有抽象方法都已实现,否则会报错。 - 这种组件级注入的方式会让每个组件实例拥有独立的
ODataService实例,正好符合你“一次性使用”的需求。
内容的提问来源于stack exchange,提问作者demo
相关产品推荐
相关产品推荐

