angular - 为什么 Angular 建议使用 FactoryProvider 来升级 ajs 服务,而不是 InjectionToken?
问题描述
在他们的文档中,他们使用这个FactoryProvider
例子来升级 ajs 服务:
import { HeroesService } from './heroes.service';
export function heroesServiceFactory(i: any) {
return i.get('heroes');
}
export const heroesServiceProvider = {
provide: HeroesService,
useFactory: heroesServiceFactory,
deps: ['$injector']
};
@NgModule({
imports: [
BrowserModule,
UpgradeModule
],
providers: [
heroesServiceProvider
],
/* . . . */
})
有什么理由不这样做InjectionToken
吗providers
?
import { HeroesService } from './heroes.service';
import {inject, InjectionToken} from '@angular/core';
import {auto} from 'angular';
export const heroesServiceToken = new InjectionToken<HeroesService>('HeroesServices', {
providedIn: 'root',
factory() {
const $injector = inject('$injector' as any) as auto.IInjectorService;
const instance = $injector.get('heroes');
return instance as HeroesService;
}
});
...
import { HeroesService } from './heroes.service';
import {Inject} from '@angular/core';
class SomeComponent {
constructor(@Inject(heroesServiceToken) private heroesService: HeroesService) {
}
}
解决方案
InjectionToken
通常没有与它们关联的值。当您需要使非令牌值可注入(即 an Interface
)时,它们很方便。我认为工厂的选项是在更高版本的 Angular 中添加的,一旦有了工厂,令牌就会有一个关联的值。因此,不应在提供程序数组中使用带有工厂的令牌。
我觉得文档使用了最常见的用例,并且更容易让人理解。
这样您就不必将它添加到需要使用的每个模块的提供程序列表中?
这种说法并不完全正确。
如果模块需要提供它,您可以将它添加到模块中的提供程序中。当一个模块需要使用它时,会注入提供者,并通过找到提供它的父注入器来解析该值。将提供程序添加到根目录往往会使每个人都可以使用它。
让提供者进入根目录可能很棘手。因此,Angular 编译器会查找注入以查看它是否正在被使用,如果它找到一个用法,编译的应用程序会将其添加到provideIn
声明中。否则,我们必须手动提供。
我说很棘手,因为let thing = injector.get(myThing)
编译器不会拾取源代码。构造函数参数和@Inject()
是我知道编译器会看到的唯一东西。
使用带有令牌的工厂隐藏了该值的生命周期。除非有人去查看令牌的声明位置,否则他们将不知道它是如何创建的。在模块中提供工厂更常见,人们会看到它。
如果您需要provideIn
与工厂一起使用,那么我认为令牌是唯一的方法。
推荐阅读
- amazon-web-services - Terraform 无法使用具有完全访问权限的附加策略文档的用户进行初始化
- icloud - Xcode 13 Beta 和 CloudKit 问题
- terraform-provider-aws - 特定 ENI 的流日志
- ios - 在不知道类型的情况下初始化 swift 变量
- angular - Angular Storybook 函数和动画
- redirect - 是否可以将 Shopify 注册的域重定向到另一个网站(Squarespace)?
- node.js - TypeScript 装饰器:将对象从装饰器注入方法
- reactjs - Pre Populate Material UI 复选框、滑块和地图字段
- reactjs - 顺风条件转换
- powershell - Powershell Start-Process 文件名或扩展名太长