如何在Angular 2中创build一个单例服务?

我已经读过注入引导应该有所有的孩子共享相同的实例,但我的主要和头组件(主要应用程序包括头部组件和路由器出口)每个获得我的服务单独的实例。

我有一个FacebookService,我用来调用Facebook的JavaScript API和使用FacebookService的UserService。 这是我的引导:

bootstrap(MainAppComponent, [ROUTER_PROVIDERS, UserService, FacebookService]); 

从我的日志logging看起来像bootstrap调用完成,然后我看到FacebookService,然后在每个构造函数代码运行,MainAppComponent,HeaderComponent和DefaultComponent之前创buildUserService:

在这里输入图像描述

杰森是完全正确的! 这是由dependency injection的工作方式造成的。 它基于分级注射器。

Angular2应用程序中有几个注入器:

  • 引导应用程序时configuration的根目录
  • 每个组件的注射器。 如果您在另一个组件内使用组件。 组件注入器是父组件的子组件。 应用程序组件(您在指定应用程序时指定的组件)具有根注入器作为父注入器)。

当Angular2试图在组件构造函数中注入某些东西时:

  • 它查看与组件相关的注入器。 如果有匹配的,就用它来获取相应的实例。 这个实例是懒洋洋地创build的,并且是这个注入器的一个单例。
  • 如果这个级别没有提供者,它将查看父级注入器(依此类推)。

因此,如果您想为整个应用程序提供单例,则需要在根注入器或应用程序组件注入器级别定义提供程序。

但是Angular2会从底部看注射器树。 这意味着将使用最低级别的提供者,并且关联实例的范围将是这个级别。

看到这个问题的更多细节:

  • 将angular色2(testing版)中的服务注入另一个服务的最佳方式是什么?

如果您在bootstrap()列出提供bootstrap() ,则不需要在组件装饰器中列出它们:

 @Component({ selector: 'main-app', templateUrl: '/views/main-app.html', directives: [ROUTER_DIRECTIVES, HeaderComponent], // DO NOT LIST PROVIDERS HERE IF THEY ARE IN bootstrap()! // (unless you want a new instance) //providers: [FacebookService, UserService] }) 

事实上,在“提供者”中列出你的类创build了一个新的实例,如果任何父组件已经列出,那么孩子们不需要,如果他们这样做,他们会得到一个新的实例。

更新

有了NgModule,现在我要做的就是创build一个带有你的服务类的“CoreModule”,并在模块的提供者中列出服务。 然后,将核心模块导入您的主应用程序模块中,该模块将向在其构造函数中请求该类的任何子项提供一个实例:

CoreModule.ts

 import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ApiService } from './api.service'; @NgModule({ imports: [ CommonModule ], exports: [ // components that we want to make available ], declarations: [ // components for use in THIS module ], providers: [ // singleton services ApiService, ] }) export class CoreModule { } 

AppModule.ts

 import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { AppComponent } from './app.component'; import { CoreModule } from './core/core.module'; @NgModule({ declarations: [ AppComponent ], imports: [ CommonModule, CoreModule // will provide service ], providers: [], bootstrap: [ AppComponent ] }) export class AppModule { } 

我知道angular有像Thierry所说的分级注射器。

但是我还有另外一个select,以防你发现一个用户不想在父进程注入的用例。

我们可以通过创build一个服务的实例来实现,并且提供总是返回的。

 import { provide, Injectable } from '@angular/core'; import { Http } from '@angular/core'; //Dummy example of dependencies @Injectable() export class YourService { private static instance: shareService = null; // Return the instance of the service public static getInstance(http: Http): YourService { if (YourService.instance === null) { YourService.instance = new YourService(http); } return YourService.instance; } constructor(private http: Http) {} } export const YOUR_SERVICE_PROVIDER = [ provide(YourService, { deps: [Http], useFactory: (http: Http): YourService => { return YourService.getInstance(http); } }) ]; 

然后在你的组件上使用你自定义的提供方法。

 @Component({ providers: [YOUR_SERVICE_PROVIDER] }) 

而且你应该有一个单独的服务,而不依赖于分级注射器。

我并不是说这是一个更好的方法,只是为了防止有人有分级注射器不可能的问题。

语法已被更改。 检查这个链接

依赖性是喷油器范围内的单例。 在下面的例子中,一个HeroService实例在HeroesComponent和它的HeroListComponent子元素之间共享。

第1步。使用@Injectable装饰器创build单例类

 @Injectable() export class HeroService { getHeroes() { return HEROES; } } 

第2步。在构造函数中注入

 export class HeroListComponent { constructor(heroService: HeroService) { this.heroes = heroService.getHeroes(); } 

第3步。注册提供商

 @NgModule({ imports: [ BrowserModule, FormsModule, routing, HttpModule, JsonpModule ], declarations: [ AppComponent, HeroesComponent, routedComponents ], providers: [ HeroService ], bootstrap: [ AppComponent ] }) export class AppModule { } 

这里是Angular 2.3版本的一个实例。 只需像这个构造函数(private _userService:UserService)那样调用服务的构造函数即可。 它会为应用程序创build一个单身人士。

user.service.ts

 import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Rx'; import { Subject } from 'rxjs/Subject'; import { User } from '../object/user'; @Injectable() export class UserService { private userChangedSource; public observableEvents; loggedUser:User; constructor() { this.userChangedSource = new Subject<any>(); this.observableEvents = this.userChangedSource.asObservable(); } userLoggedIn(user:User) { this.loggedUser = user; this.userChangedSource.next(user); } ... } 

app.component.ts

 import { Component } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { UserService } from '../service/user.service'; import { User } from '../object/user'; @Component({ selector: 'myApp', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { loggedUser:User; constructor(private _userService:UserService) { this._userService.observableEvents.subscribe(user => { this.loggedUser = user; console.log("event triggered"); }); } ... } 

@Injectable装饰器添加到服务中,并将其注册为根模块中的提供者将使其成为单例。

这似乎对我很好

 @Injectable() export class MyStaticService { static instance: MyStaticService; constructor() { return MyStaticService.instance = MyStaticService.instance || this; } } 

您可以在提供程序中使用useValue

 import { MyService } from './my.service'; @NgModule({ ... providers: [ { provide: MyService, useValue: new MyService() } ], ... })