Creating your own services in AngularJS can be confusing. What are the differences between an AngularJS module's Service, Provider and Factory functions? This lesson shows how Angular's provider function is just a configurable JavaScript module.
[00:01] Sometimes you want a service that's configurable like the HTTP service built into Angular. The way you configure a service is to go into the DotConfig function of the module, and send in the companion provider object to your service. HTTP has an HTTP provider which can be used to configure the HTTP service.
[00:25] We could do things like set caching to "true" for requests, so that all requests made throughout the application, such as this one and this controller, would get cached. That's a concrete example of how a service can have a provider that's configurable once in the application. Then that configuration affects all uses of the service inside the application.
[00:55] Now that we've seen a provider, let's create one in plain JavaScript. We create a function called say, "droid-provider," and the function returns an object. The interface for this object, first of all, have a function to configure the service. The name configure here is not important to Angular. It can be named anything like, "set base URL."
[01:22] I'm naming it "configure" here, for clarity. Then there is a $get function whose name is important. The get-function is what will return the actual service object itself. We'll go ahead and implement our service. We'll give it a name property and a speak function. We'll have the speak function, say, return, "Hi, I am" and then concatenate the name to that.
[01:57] To use this provider function we created, it's a two-step process. First, we get a reference to the provider object itself. If I called droid-provider here, what I'll get back into the provider object is this object, which will have both a configure and a get method. Again, the configure method is to configure the object. The get method is to return the instance of the object.
[02:27] I'll go ahead and call configure on our provider. We won't actually configure it yet. We'll come back and do that in a second. Then I can create a local variable, "droid," and tell the provider to get me an instance of the service object itself.
[02:48] What's happening when I call get here is, it calls $get right there, which will return me an object. I can then work with the object. I can say, "droid.name = IG88." Then I can log out the droid speaking. If I hit save, I get, "Hi, I am IG88" over here in the console.
[03:16] Now to make this configurable, what we'll need to do is pull out this, "Hi, I am," and introduce a variable called, "greeting." I'll make that variable private up here and initialize it to an empty string. We can then pass a settings object into our config function and set the greeting. We'll set it simply to the settings object's greeting property.
[03:47] This may be confusing because I don't have a greeting property, yet. But what we can do is come down here to where we configure our provider, pass in a settings object, give it a greeting property, and then set this to something different. Let's say, "Greetings, I am." If I save now I get, "Greetings, I am IG88."
[04:14] OK, now that we've seen how to create a provider object in plain JavaScript, let's take our provider object, switch over to our empty Angular application, and paste the code across. Register this provider with Angular by saying, "dot provider," off the module. We'll give it a name of, "droid," and point at our droid provider.
[04:42] If we then ask for an instance of a droid and set the droid's name to IG88, and then log out to the message property on our controller, the droid speaking, and save, we should see, "IG88" here.
[05:04] Now notice, we don't see, "Hi, I am," yet or any type of greeting, because we haven't configured the object. To configure our service using our provider we call the DotConfig function of the module. We ask for an instance of the droid provider. This will send us an instance of the object that's being returned right here, so we'll have a configure function on it and a get function on it.
[05:31] We can go ahead and configure our droid service. We can pass in a settings object, give that a greeting property, set that equal to, "Greetings, I am," and then save. We get, "Greetings, I am IG88," because we've configured our object using a provider.
[05:59] It's important to understand that this droid provider here being passed in, is not this function. It's the result of this function being invoked, which returns us this object literal here, which then has a configure function and $get function.
[06:17] This name of droid provider is by convention. When we register the provider with the name "droid," we get two objects. We get the service itself named "droid," and we get droid with the word "provider" appended, which represents this first outer object that's being returned.
[06:38] To recap, if you want a service that's configurable, you'll need to return an object that has two functions. One to configure the object and one to get the object. The $get function name is important here, because Angular needs to know to call that one. You'll be calling this function, so it's not as important what you name it.
[07:01] To register this provider object with Angular, you call dot provider and pass it that function. Angular then knows that when you ask for this object plus the word "provider" to return this outer object, which will give you both a configure and a get.
[07:19] You can then call the configure function and configure your service. Then, when you ask for your service as we did down here in the controller, Angular will use this provider object and call the get method on it. Which will return you an instance of an object as your service, and that will be dependency injected where you ask for it.