Search code examples
angulartypescriptangular2-routingangular2-services

How do I create a singleton service in Angular 2?


I've read that injecting when bootstrapping should have all children share the same instance, but my main and header components (main app includes header component and router-outlet) are each getting a separate instance of my services.

I have a FacebookService which I use to make calls to the facebook javascript api and a UserService that uses the FacebookService. Here's my bootstrap:

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

From my logging it looks like the bootstrap call finishes, then I see the FacebookService then UserService being created before the code in each of the constructors runs, the MainAppComponent, the HeaderComponent and the DefaultComponent:

enter image description here


Solution

  • Jason is completely right! It's caused by the way dependency injection works. It's based on hierarchical injectors.

    There are several injectors within an Angular2 application:

    • The root one you configure when bootstrapping your application
    • An injector per component. If you use a component inside another one. The component injector is a child of the parent component one. The application component (the one you specify when boostrapping your application) has the root injector as parent one).

    When Angular2 tries to inject something in the component constructor:

    • It looks into the injector associated with the component. If there is matching one, it will use it to get the corresponding instance. This instance is lazily created and is a singleton for this injector.
    • If there is no provider at this level, it will look at the parent injector (and so on).

    So if you want to have a singleton for the whole application, you need to have the provider defined either at the level of the root injector or the application component injector.

    But Angular2 will look at the injector tree from the bottom. This means that the provider at the lowest level will be used and the scope of the associated instance will be this level.

    See this question for more details: