Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a Service or a Provider? Confused by Angular tutorial

I'm currently following the Angular tutorial on their main website, and I'm having difficulty with one of their concepts. It feels loose in the way it refers to what is the Service and what is the Provider, I can't tell if its one or the other. The link takes you right to the problem part of the tutorial.

https://angular.io/tutorial/toh-pt4#injectable-services

So far as I can tell, a Service is used to serve data to Components. Components gain access to Services by having the Services Injected into them. However, the Injector is something that exists in its own right, and the Service needs to be made avilable to it, before it can inject it.

However, the guide that I'm reading feels loose in the way it refers to what is the Service and what is the Provider. At first I thought the entire Hero.Service.ts was the Service. Then it says that @Injectable marks the class as the Service. Okay fine, and yeah that's how Components work, the Decorator specifies what it is. But then the guide says,

"The HeroService class is going to provide an injectable service"

Wait, so HeroService isn't the service, it provides the service object? Remember the words "is going to provide an injectable service", as it comes up later.

The guide goes into a little detail about how the Service retrieves data for Components, and then comes to how Services need to be introduced to the dependency injector via Providers.

Here's the trouble. It says that the Provider creates or delivers the Service, in this case instantiating HeroService. Then it says that HeroService is going to be the Provider of HeroService. To repeat, here are two lines in which they refer to the HeroService as a Service

Implicitly: "You must make the HeroService available to the dependency injection system before Angular can inject it into the HeroesComponent"

Again implicitly "You do this by registering a provider. A provider is something that can create or deliver a service; in this case, it instantiates the HeroService class to provide the service."

Before the tutorial header Create HeroService " They should focus on presenting data and delegate data access to a service...In this tutorial, you'll create a HeroService that all application classes can use to get heroes." Note: heroes is the data

However, then they say that HeroService is registered as the Provider? "Now, you need to make sure that the HeroService is registered as the provider of this service" If HeroService is the Provider, what is "this service" referring to?

Now remember the line "HeroService class is going to provide an injectable service"

So I have two lines of a tutorial referring to HeroService as a Service, and another two lines saying that it's a Provider. Unless, in the latter case, they were using the word "provide" or "service" in a way that was strictly colloquial and wasn't actually referring to to Providers and Services.

like image 633
Joel Nash Avatar asked Aug 08 '18 23:08

Joel Nash


People also ask

What is provider and service in Angular?

In Angular, a service can be anything from a simple value, a function, or a feature that your application needs. In most cases, however, services in Angular are classes that perform some specific function. To be able to use a service via dependency injection you must register it with at least one provider.

What is difference between factory service and provider in AngularJS?

The major difference between an AngularJS service and an AngularJS factory is that a service is a constructor function and a factory is not. That is why, in the case of a factory, we return an object literal instead of using this.

What is the difference between services and components in Angular?

Services are used for common methods for some common functions across the different Component. They are simple classes with functions and members not html content. Used when - wanted to reduce duplication of code, to access or store data.

What is a service in Angular?

What Are Angular Services? Angular services are objects that get instantiated just once during the lifetime of an application. They contain methods that maintain data throughout the life of an application, i.e., data is available all the time.


1 Answers

It feels loose in the way it refers to what is the Service and what is the Provider, I can't tell if its one or the other.

A Service is a JavaScript object that exists in your application, and a Provider is the way you gain access to that object. The two are not the same thing, but they work together to make your Service accessible from other places. You can't get your Service without a Provider, and a Provider needs something to provide.

A Service is just a term used to describe an instance of an object (which is often a TypeScript class). We call them Services because this term is often used in dependency injection to describe a shared object that performs a single purpose.

"The HeroService class is going to provide an injectable service"

Here the word provide refers to the verb in the grammar. It should not be confused with the TypeScript type Provider which is used by Angular to define an entry in the list of providers.

A better way of writing the above sentence:

"The HeroService class is going to declare an injectable service"

I agree with your claims that it's confusing. So I'll just explain how things work.

Providers

A single provider is a JavaScript object that implements the Provider interface (it's actually multiple interfaces), but my point is that it's an object that tells Angular how to associate a token with a value.

Only a NgModule can define providers at compile time. We often do it like this:

@NgModule({
     providers: [HeroService]
})

Now, remember above I said that a provider was a JavaScript object, but in the NgModule example we don't define an object. We just use HeroService which is technically a constructor function.

This is to make it easier for the programmer. At compile time Angular will look at HeroService to see what the metadata says about it, and it will automatically generate the provider object.

That metadata is created by doing the following.

 @Injectable()
 export class HeroService {}

The @Injectable decorator adds hidden metadata that describes how to create a HeroService instance.

We can do the same thing by defining the provider object ourself, and if we do it using a provider object the service doesn't need a @Injectable decorator, because we are creating it ourselves.

@NgModule({
     providers: [{provide: HeroService, useValue: new HeroService()}]
})

So we can now explain why they said "The HeroService class is going to provide an injectable service". It's because HeroService uses the @Injectable decorator to declare the provider for the service.

Injecting

Angular does a lot of work for you. When you are writing a component and you want to inject the HeroService so that you can use it. All you have to do is the following.

 @Component({....})
 export class AppComponent {
       constructor(heroService: HeroService) {
                             // ^^^ this is the provider token
       }
 }

The above works because Angular can infer which providers are needed by the constructor. It looks at the first argument and sees that the type is HeroService. We call this the injectable token, and Angular can search through the providers looking for one where it has provide: HeroService. It then uses that provider to get the value and pass it to the constructor.

We can break dependency injection by doing the following.

 @Component({....})
 export class AppComponent {
       constructor(heroService: any) {
                             // ^^^ this is an unknown provider
       }
 }

Angular can no longer infer the token for the provider. It doesn't know which of the many providers that are declared is the one the programmer wanted to use.

We can declare which provider token we really want.

 @Component({....})
 export class AppComponent {
       constructor(@Inject(HeroService) heroService: any) {
                        // ^^^ we declare the token manually
       }
 }

When Angular needs help we use the @Inject decorator to manually declare which provider token should be used.

Singletons

In Angular 6 a new feature was introduced that allowed you to declare a Service as a provider in the root module. It's the "providedIn" option for injectables.

 @Injectable({ providedIn: 'root' })
 export class HeroService {}

Above I said that @Injectable makes it easier to add classes to the providers array in a NgModule. Well, the providerIn takes it one step further and now adds it for you directly to the module.

These things can be confusing, because they hide the underlying work that the dependency injection system is doing. It makes more of the features look like magic instead of illustrating what they're doing.

like image 191
Reactgular Avatar answered Oct 13 '22 23:10

Reactgular