使用同一服务的多个实例

时间:2016-07-20 13:14:21

标签: angular angular2-services

我有这样的服务:

@Injectable()
export class EditorService { ... }

我有一个组件,如下:

@Component({
    ...
    template: `<child-component></child-component>`,
    providers: [EditorService],
    ...
})
export class SomeComponent {
    constructor(
        private _appleEditorService: EditorService,
        private _pearEditorService: EditorService) {}
}

您可能已经注意到,此组件具有子组件:

@Component({
    ...
    selector: 'child-component',
    ...
})
export class ChildComponent {
    constructor(
        private _appleEditorService: EditorService,
        private _pearEditorService: EditorService) {}
}

如您所见,我想要EditorService的两个实例:一个用于编辑苹果,另一个用于编辑梨。但是,上面的代码不起作用,因为Angular无法知道哪个EditorService实例的变量名是私有的。 _pearEditorService中的ChildComponent也可能在_appleEditorService中引用与SomeComponent相同的实例。

问题:那么,我可以两次使用相同的Angular2服务吗?

编辑:我的问题是,是否可以使用同一个类。我知道有一些解决方法是为服务的每个实例创建一个单独的类,甚至通过继承实现少量代码。我只想知道是否可以不用。

4 个答案:

答案 0 :(得分:37)

Angular DI为每个提供商维护一个实例。在您的情况下,如果您有两个具有相同类型的构造函数参数,它们将解析为同一个实例。

您可以做的是提供工厂功能(不同于简单的useFactory提供者事件,尽管它也使用它)

(从https://stackoverflow.com/a/37517575/217408复制的示例)

{ provide: EditorService, useFactory: 
    (dep1, dep2) => {
        return (x) => { 
            new EditorService(x, dep1, dep2);
        }
    }, deps: [Dep1, Dep2]
})

....

constructor(@Inject(EditorService) editorServiceFactory: any) {
  let editorService1 = editorServiceFactory(1);
  let editorService2 = editorServiceFactory(2);
}

如果你有一定数量的实例,这应该有效:

{ provide: 'instance1', useClass: EditorService },
{ provide: 'instance2', useClass: EditorService },
export class SomeComponent {
    constructor(
        @Inject('instance1') private _appleEditorService: EditorService,
        @Inject('instance2') private _pearEditorService: EditorService) {}
}

答案 1 :(得分:2)

可能会重新考虑您的设计

我认为你可能不得不重新考虑你的设计。有两个变量指向完全相同的EditorService的重点是什么?如果他们共享相同的实现。

继承解决方案

对此的解决方案可能是使用继承。我没有看到你的服务所以我不确定他们做了什么,但从这段代码我假设&#34; apple&#34;功能和&#34;梨&#34;功能实际上是不同的。然后这表明您可能有一些设计问题,而您的EditorService可能做得太多了。也许您可以将Apples和Pears类似的代码移动到名为EditorService的服务,然后有两个类扩展它。一个AppleEditorService和一个PearEditorService

使用general fruitService

再谈谈为什么我认为您可能需要重新考虑您的设计。让我们假设appels和梨实际上具有相同的功能。所以EditorService做同样的事情。您希望将一个变量用于&#39; Apples&#39;和#Pears&#39;。如果我看到该代码(假设其他人在您的团队中工作),并且我注意到这两个变量都指向同一个服务。 (服务是单身人士),我很想去除它并制作类似fruitService : EditorService之类的东西。

无论哪种方式,你的问题都让我觉得应该改变设计。你不想要两个服务实例,服务是单身的,虽然你可以找到解决方法,但我认为这不是你问题的解决方案。

但正如我之前提到的那样。想想你的设计。你真的需要两个儿童服务,或者你能以不同的方式解决它吗?你能把苹果和梨子作为水果的子类吗?你能使用一个变量&fruitService&#39;而不是苹果/梨?当你想要储存&#34;草莓&#34;以及将来?有一堆变量引用相同的服务(因为它们做同样的事情)但是使用不同的变量名称​​不是一个好主意。想象一下在代码中看到这个

 appleService = EditorService;
 pearService = EditorService;
 starwberryService = EditorService;
 lemonService = EditorService;
 ...
 guavaService = EditorService;

这不会表明代码有些奇怪吗?我可以想象(你现在没有提供代码)你存储了一个fruitInstances数组。但是,也许一个fruitService可以工作,然后存储fruitService.store(Apple a)并将其放入一系列“水果”中。使用&#39;过滤器&#39;从阵列中获得正确的水果不应该太难。

^这只是在没有更多代码的情况下编写的。如果你编辑你的问题,有些事情可能不再适用了。

答案 2 :(得分:0)

不太理想,但是如果您为每个组件创建一个模块,然后在每个模块上导入服务,则将有2个相同服务的实例(每个模块一个)。

答案 3 :(得分:0)

如何使用服务中的对象来存储 X 数量的实例...

export class Test {

  private vars: any;

  constructor() {
    vars = {};
  }

  createInstance(var: any) {
    this.vars[var] = var;
  }

  doSomething(var: any, options): void {
    this.vars[var] = someChangeToVar;
  }

  doSomethingElse(var: any): void {
    this.vars[var] = someOtherChangeToVar;
  }

  get var(var: any): any {
    return this.vars[var];
  }

}

你调用它时的第一个参数是实例的名称...

export class SomeComponent {

  constructor(private test: Test) {

    // create instance
    this.test.createInstance('myInstance');

    // do something to it
    this.test.doSomething('myInstance', 'some input here');

    // get it back
    const result = this.test.get('myInstance');

    console.log(result);
  }
...
}