11

I just switched my application over to be lazy-loaded today.
I have a SharedModule that exports a bunch of services. In my AppModule, I import SharedModule because AppComponent needs access to a few of the shared services.

In another module FinalReturnModule, I import SharedModule. In one of my services, I put a console.log('hi') in the constructor.

When the app first loads, I get hi to the console. Whenever I navigate to a page within the FinalReturnModule I get hi again. Obviously, since there are two instances, nothing's working correctly since the modules aren't able to communicate.

How can I stop the service from being instantiated twice?

EDIT: Background, the app is built using angular-cli.

Current versions:

angular-cli: 1.0.0-beta.24
node: 6.9.1
os: win32 ia32
@angular/common: 2.4.1
@angular/compiler: 2.4.1
@angular/core: 2.4.1
@angular/forms: 2.4.1
@angular/http: 2.4.1
@angular/platform-browser: 2.4.1
@angular/platform-browser-dynamic: 2.4.1
@angular/router: 3.1.1
@angular/compiler-cli: 2.4.1
Alex Kibler
  • 3,924
  • 8
  • 38
  • 64

1 Answers1

20

If the service is truly meant to be a singleton (one created once), don't add it to any module that will be a part of a lazy-loaded module (e.g. in the SharedModule). The reason is that lazy-loaded module get their own instances of services. If you want the service to be truly a singleton, then add it just to the AppModule, or the "Core Module" that will get imported only to the AppModule. Or you can use forRoot which will only be called in the AppModule

import { ModuleWithProviders } from '@angular/core';

@NgModule({
  declarations: [...],
  imports: [...]
})
class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [ MySingletonService ]
    }
  }
}

@NgModule({
  imports: [ SharedModule.forRoot() ]
})
class AppModule {}

@NgModule({
  imports: [ SharedModule ]
})
class OtherModule {}

Now the AppModule is the only module that imports the module with the providers.

See Also:

Stefan Falk
  • 18,764
  • 34
  • 144
  • 286
Paul Samsotha
  • 188,774
  • 31
  • 430
  • 651
  • Lifesaver. Thank you! – Jonathan Grupp Apr 09 '18 at 14:54
  • In most cases I see, providers are supposed to be singletons (except for some specific cases). For small apps this approach may seem fine, but as the app grows you end up declaring a lot of providers in AppModule, making the initial load size larger and consequently slower. Is there some recommendation regarding that? Like defining one global provider that store the state of other providers and import it in AppModule and import all other providers only where they are used (accessing the global provider to retrieve and define state, instead of relying in itself). Or something along these lines? – Lucas Basquerotto Apr 20 '18 at 12:52
  • It seems that `{providedIn: 'root'}` config in the service is enough to tell angular to create only one instance of it, even if it's included in lazy loaded component (available in Angular 6.0) => https://angular.io/guide/singleton-services – Paul Giragossian Mar 25 '19 at 12:51