Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Singleton Services?

In Angular 1 I frequently used factories for services to store shared state accessible by many components. It looks like in Angular 2 all services that are injected as @Injectable() are created each time, thus losing the shared state.

I 'register' the service at the root module's providers meta key, but still I get a transient instance.

What I have:

Injectable()
export class ArtistService {
   constructor(private http:Http) {
     // firing on each injection
     console.log("ArtistService ctor");
   }

}

to call it in a component then:

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

And the definition of the module:

@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]
})

I suspect there is maybe some other way to 'register' the ArtistService so it stays loaded as a static instance? Is that possible via DI or is it necessary to create a static instance method manually?

Update:
Turns out that the above code does work. I was looking in the wrong place along with a logic error that caused data not to cache correctly.

The above code works and assigning the service in the providers section of the top level AppModule is the key to making the parent reference stay loaded for the duration of the AppComponent. which effectively stays loaded for the lifetime of the app providing the Singleton instance.

To get a transient instance you can declare the providers meta tag and the service name on the actual component which will then create the service whenever the component is loaded/re-loaded.

like image 677
Rick Strahl Avatar asked Sep 02 '16 04:09

Rick Strahl


People also ask

Are services in Angular singletons?

The answer would be no. The main objective of angular services is to share data across Angular application. Practically an angular service can be shared between all the components or can be limited to some component. Hence Angular service can be a singleton as well as non-singleton in nature.

How can we make service as singleton in Angular?

There are two ways to make a service a singleton in Angular: Set the providedIn property of the @Injectable() to "root" Include the service in the AppModule or in a module that is only imported by the AppModule.

Is Angular router a singleton?

A routed Angular application has one singleton instance of the Router service.

What is a singleton in Angular?

A singleton is a class that allows only a single instance of itself to be created and gives access to that created instance. It contains static variables that can accommodate unique and private instances of itself. It is used in scenarios when a user wants to restrict instantiation of a class to only one object.


1 Answers

What you have shown is a correct way. It creates single instance which will be shared among components.

https://plnkr.co/edit/FBCa39YC4ZPoy6y8OZQl?p=preview for reference purpose.

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 { }
like image 115
Nikhil Shah Avatar answered Oct 21 '22 08:10

Nikhil Shah