Angular 2 - 单例服务?

8
在 Angular 1 中,我经常使用工厂来创建服务以存储被许多组件访问的共享状态。看起来在 Angular 2 中,所有被注入为 @Injectable() 的服务都会每次都被创建,从而导致共享状态丢失。
我将服务注册到根模块的 providers 元数据关键字中,但仍然获得了一次性实例。
我的情况是:
Injectable()
export class ArtistService {
   constructor(private http:Http) {
     // firing on each injection
     console.log("ArtistService ctor");
   }

}

在组件中调用它:

@Component({
    selector: 'artist-display',
    templateUrl: './artistDisplay.html',
})
export class ArtistDisplay  {
    constructor(private artistService: ArtistService) {
           // instance is fine but transient
    }
}

这里是关于模块的定义:

@NgModule({
  declarations: [...],
  imports: [BrowserModule, FormsModule, HttpModule,
    RouterModule.forRoot(rootRouterConfig)],
  providers   : [
      ArtistService,

      // make sure you use this for Hash Urls rather than HTML 5 routing
      { provide: LocationStrategy, useClass: HashLocationStrategy },
  ],
  bootstrap: [AppComponent]
})

我怀疑可能有其他方法来“注册”ArtistService,使其作为静态实例保持加载?这是否可以通过DI实现,还是必须手动创建静态实例方法?
更新: 事实证明上述代码确实可行。我在错误的位置查找,并且逻辑错误导致数据无法正确缓存。
上述代码有效,并将服务分配到顶层AppModuleproviders部分是使父引用在AppComponent的生命周期内保持加载的关键。这有效地保持应用程序的生命周期提供了Singleton实例。
要获取瞬态实例,您可以在实际组件上声明providers元标记和服务名称,这样每当组件加载/重新加载时就会创建服务。
4个回答

3

我也想创建一个在angular2中用作提供者的对象,所以我创建了一个@injector。 但是如果我们在每个@component中设置提供者并导入它,那么每个组件将使用不同的@injector对象。 为了创建单例提供者,我在父组件中声明了该提供者,并在每个组件中导入它,现在它可以正常工作。 https://angular.io/guide/dependency-injection


2
提示:我已经读了你的答案三遍,但仍然不确定你想要表达什么。如果英语不是你的母语,请使用简短的主谓宾句。专注于编写易于理解的文本! - GhostCat

3
您展示的是正确的方法。这将创建一个单独的实例,该实例将在组件之间共享。
参考链接:https://plnkr.co/edit/FBCa39YC4ZPoy6y8OZQl?p=preview
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';
import {service} from './service';
@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent],
  providers:[service],

  bootstrap:    [ AppComponent ]
})
export class AppModule { }

6
嗯...这对我没用。每次注入到ArtistDisplayComponent中时,服务构造函数都会触发。 - Rick Strahl
看,我已经添加了一个工作链接,它显示了共享服务。 - micronyks
好的,我再次确认了,它确实正常工作。这是我的操作错误 - 我看错了 console.log() :-) - Rick Strahl
2
我仍然不知道当您只有一个组件时如何显示其为单例。为了检查它是否为单例,需要有2个组件注入相同的服务。 - Tek
7
在appmodule中提供“providers:[service]”,可以使其成为单例模式。如果您单独在不同组件中注入它,则每个组件都将有自己的实例。因此,为了使其成为单例模式,您必须将其添加到appModule的ngModule中,或者您可以创建一个coremodule(在官方网站上阅读更多)。 @Tek - micronyks

2

单例服务只能放在app.module.ts "providers" (array)中,不能放在其他组件或服务提供商(数组)中。

如果正确地执行此操作,则Angular 2 - 2.4.0 - 单例将完美运行。


1

好的,让我尝试解释一下服务是如何工作的,根据我的经验和基本文档,有三种主要情况:

  • 服务包含在组件级别的提供者数组中 - 该服务可以注入到父组件和所有子组件中。

  • 服务包含在模块级别的提供者数组中 - 在此模块中的所有内容都知道该服务。

  • 服务包含在模块级别的提供者数组中 - 在此模块中的所有内容都知道该服务,但如果您在另一个导入第一个模块的组件内使用来自此模块的组件,则此组件的服务实例将不同。


你救了我!我的component1没有注入服务,而component2已经注入了服务。在我从component2提供者中移除服务之前,我无法获得单例。谢谢! - praHoc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接