What are providers in Angular2?

Providers are usually singleton (one instance) objects, that other objects have access to through dependency injection (DI).

If you plan to use an object multiple times, for example, the Http service in different components, you can ask for the same instance of that service (reuse it). You do that with the help of DI by providing a reference to the same object that DI creates for you.

@Component){
  ..
  providers: [Http]
}

..instead of creating new object every time:

@Component){}
class Cmp {
  constructor() {
    // this is pseudo code, doens't work
    this.http = new Http(...options);
  }
}

This is an approximation, but that's the general idea behind Dependency Injection - let the framework handle creation and maintenance of reusable objects... Provider is Angular's term for these reusable objects (dependencies).


Register injectables

Providers make injectables known to Angular's DI and define the scope of an injectable (service).

Hierarchy of injectors

Angular's DI creates a tree of injectors (parent > child > grandchild >...) that resembles the structure of your components and directives.

Single instance per provider

Providers are maintained per injector. Each provider provides a single instance of an injectable.

Provider lookup

When a component or directive has a dependency (constructor parameter), DI starts looking on this component's injector for providers. If it has one it requests the instance from this provider and injects it.

If the injector doesn't have a provider for the requested key (type) then the parent injector is visited, up to the root (bootstrap) until a provider is found and its instance can be injected. (If no provider is found DI throws an error).

Define the scope of an injectable instance

This way you can define the scope of a shared service, because DI starts looking from the component where an instance is requested upwards until it finds one.

Singleton or not

How many places you provide an injectable determines how many instances will be created (they are only instantiated if actually requested).

If you want a single instance for your whole application, then provide an injectable only once at the root component (or with bootstrap(AppComponent, [...]) which results in the same behavior.

If you want a new instance for each component A, then add it to providers of the component A.

(update) NgModule lazy and non-lazy

With the introduction of NgModule modules, additional levels were introduced. Providers registered with non-lazy-loaded modules are above the root component in the hierarchy.

Lazy-loaded modules are above the components and directives loaded by these components.

Because providers are read-only after an injector is created, there is no way to add providers from lazy loaded modules to the root injector. Therefore, lazy loaded modules get their own root scope.

See also https://stackoverflow.com/a/45231440/217408