与功能请求相关的@angular/*包有哪些?
- 无响应*
描述
独立组件带来了巨大的责任,尤其是在服务生命周期方面。
问题在于组件需要一些服务,而且要猜测哪些服务已经被添加到providers
的上一级,哪些服务应该重新开始(因为它们有状态,不应该被子组件意外地修改)等等。
我的经验是,这导致了providers: [...]
的过度使用,因为它往往是从父级组件中猜测可用的服务提供者,而哪些服务没有被使用。
尽管拥有自己的providers[...]
有一个不好的味道,但基本上子组件可以忘记自己的服务提供者——一切都能正常工作——但这将导致它们意外地共享服务。
所以如果故意这样做是可以的,但我的经验是这种情况发生的概率很大,导致难以调试的问题。
建议的解决方案
我建议一个类似于inject(...)
的方法,只是它确保创建的服务只创建一次,永远不会被重用。
这将使得代码比以前更短、更好看(以前你永远无法确保子组件会重用你的服务):
@Component({
// selector etc.
})
export class Example {
private = transient(ViewService);
}
...而不是这样:
@Component({
// selector etc.
providers: [
ViewService,
],
})
export class Example {
private = inject(ViewService);
}
transient(...)
的工作代码看起来像这样——但我相信还有改进的空间:
import { Injector, ProviderToken, TypeProvider, inject } from '@angular/core';
/**
* Transient dependency injection provider.
* This will create a new instance of the provided token,
* without making it available in sub-components
* as would happen with providers in a component.
*
* @param token the class which is injectable
* @param injector the injector to use, if not provided, the current injector will be used.
* Not not necessary when using transient in the class properties construction or in the constructor,
* as the injector will be available in the constructor.
* But necessary when using transient inside anything else.
* @returns
*/
export function transient<T>(token: ProviderToken<T>, injector?: Injector): T {
// make sure we have an injector
// this will throw an error, if transient is used outside of construction and without providing an injector
injector ??= inject(Injector);
// create a new injector which is only meant to be used for this transient instance
const subInjector = Injector.create({
providers: [
token as TypeProvider
],
parent: injector
});
// return the instance
return subInjector.get(token, undefined, { self: true });
}
考虑过的替代方案
我想我们还可以:
- 扩展inject-options以为此提供标志,但我认为这会更简单、更清晰。
- 更改服务的签名,使它们可以被标记为
transient
,从而注入器总是创建一个新的服务——无论如何,这都是一个受欢迎的补充,但我对transient(...)
注入器的推荐仍然很好,因为你不需要定义providers
就可以获得一个服务。
2条答案
按热度按时间bgibtngc1#
我们正在讨论一个类似的API,这个功能将允许我们创建一个可注入的示例(通过解析其依赖项从注入器),但不将其本身注册到注入器中。
标记作为一个功能请求 - 它需要API设计,尽管如此。
im9ewurl2#
如果我可以添加另一个相关点:如果服务只能被标记为 transient ,那就很好了,这样它们永远不会被共享/重用,并且每次都会为每个
inject(...)
重新创建。