Ember 2.x Services
This course has been updated! We now recommend you take the Ember Octane Fundamentals course.
Transcript from the "Services" Lesson
>> Mike North: Services are a concept that was added late in the 1.x series of Ember releases. And they're an effort to hold long-living application state and shared application functionality in a place that is flexible. And where you can use dependency injection to make it available appropriately without risk of polluting your application.
[00:00:37] So, they are created when your application starts up, and they're different than other objects in the Ember world, controllers aside. In that, everything is sharing this single instance, right? Everything is sharing this one service. They live in the /app/services folder. And other than that they're very simple objects, and it's really up to you to customize it as you see fit.
[00:01:07] So a great use of the service would be for authentication. You could have a service that would actually make a request to an API to authenticate a user. And then store the current user as an object on the service itself so that it could be made available to templates and components, which need to render an avatar on the screen.
[00:01:31] It can be made available to parts of your application that send API requests, so they would pass credentials along. And they could be made available to routes so that you would know if you have to kick an unauthenticated user out to a login page. But this is a great example where you have like one concern which is current user and the need to authenticate someone.
[00:01:53] But you have many flavors of object that need to know about this thing, and you could use a global to do this. You could just make something available to everyone but that becomes a maintenance nightmare. And this really lets you be very specific that this route should have access to this and this component and nothing else.
>> Mike North: So the way you add a service to an object, you essentially add a service as a property to an object. And you just use this Ember.inject.service method, and what it will return is, this is essentially a computer property which we're going to get into in a second.
[00:02:40] But it lets you directly access whatever's on the service from within the object that this thing is injected onto. So the name is optional and I will, in my, I'll do a little pre-example before we pose our problem just to illustrate how this works, there's a nice clean convention that makes this thing really readable and easy.
[00:03:04] And it's lazily evaluated, which means that only when you ask for it is the value actually fetched, and the work done to actually calculate what needs to be calculated. Services work on just about any Ember object. So, again, very flexible means of sharing functionality and state. And I'm actually gonna stop there because there's not much to these except the advised use of them, but other than that it's a blank slate for whatever specific functionality is needed.
>> Speaker 2: So they're asking, he's currently using an initializer to store and inject something like the system date. Is this recommended to do in a service?
>> Mike North: Yes, so the previous the old discouraged way of doing things was to use another object in Ember that is a singleton, and here I am talking about it again, controllers.
[00:04:11] And you would basically create a controller and use an initializer, which is something that you use to customize the startup process of your app. And it would essentially make it available on a bunch of different objects. The fact that you're creating a service here, like Ember will do it for you, Ember will start it up.
[00:04:32] And instead of using an initializer to inject this in various places, you're actually gonna just, as you define these various objects that need to know about a service. You will just say, I've got this authentication service and here it is and it can be done at class construction time, instead of at app start up time.
[00:04:57] And it's a little nuanced but in terms of reading through code and understanding, you don't have to go and check in on some separate piece of code, is this other thing injecting something on to me. It's all available in this one object, the things that have been injected on to it, if that makes sense.
[00:05:18] So, I can see in the source code of the route that I have access to authentication. I don't have to look through a folder of a bunch of initializers and hunt down where someone has operated on me. So this is definitely the advised way of doing it.
>> Mike North: All right.
>> Speaker 2: And then one other question, can the services access the store?
>> Mike North: Good question. I will have to investigate that one and I will come back with the answer.
>> Speaker 3: If they don't have it available but you can use an initializer to inject the store into a service?
>> Mike North: Yes.
>> Speaker 3: But by default it isn't available into the service.
>> Mike North: Yes.
>> Speaker 4: The store has a service into a service?
>> Mike North: You have the store, I'm not sure, in it's current form, whether the store is a service.
>> Speaker 3: The store is, in general.
>> Mike North: Okay, so you can inject-
>> Speaker 3: You can inject a service into a service, and you can inject the store as a service into anything that you want to.
>> Mike North: Interesting. Yeah, the idea is to get away from initializers doing the injection itself, and to really rely on the common idiom of have the singleton.
[00:06:32] It needs to be made available on objects. And then there's the benefit of moving the actual description of the injection act itself and the object that you're injecting on to. So that you can see it and you can manage it there rather than having to worry about searching for some container string and all of the hoops you have to jump through, the old way of doing things.