angular 特性: transient (...)函数,以补充注入(...)函数,

lyr7nygr  于 3个月前  发布在  Angular
关注(0)|答案(2)|浏览(42)

与功能请求相关的@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 });
}

考虑过的替代方案

我想我们还可以:

  1. 扩展inject-options以为此提供标志,但我认为这会更简单、更清晰。
  2. 更改服务的签名,使它们可以被标记为transient,从而注入器总是创建一个新的服务——无论如何,这都是一个受欢迎的补充,但我对transient(...)注入器的推荐仍然很好,因为你不需要定义providers就可以获得一个服务。
bgibtngc

bgibtngc1#

我们正在讨论一个类似的API,这个功能将允许我们创建一个可注入的示例(通过解析其依赖项从注入器),但不将其本身注册到注入器中。
标记作为一个功能请求 - 它需要API设计,尽管如此。

im9ewurl

im9ewurl2#

如果我可以添加另一个相关点:如果服务只能被标记为 transient ,那就很好了,这样它们永远不会被共享/重用,并且每次都会为每个 inject(...) 重新创建。

相关问题