Implementing Services in an Ember.js Application

2014-05-15

The following examples assume your project uses ember-cli. Names of files and objects will be a little different if you're working in globals mode.

Define the service in the file app/services/myservice.js:

export default Ember.Object.extend({
  logFoo: function () {
    console.log("foo");
  },
});

Initialize the service using an initializer under app/initializers/services:

export default {
  name: "services",
  initialize: function (container, app) {
    // Inject into all routes and controllers
    app.inject("route", "myService", "service:myservice");
    app.inject("controller", "myService", "service:myservice");

    // Or if you wanted, into a specific route
    app.inject("route:some-route", "myService", "service:myservice");
  },
};

Your service is now available in the classes you specified. Try it out by with this.myService.logFoo() in a route.

You can also inject other objects into a service:

export default {
  name: "services",
  initialize: function (container, app) {
    // Make the ember-data store available in the service
    app.inject("service:myservice", "store", "store:main");

    // Then inject service into all routes
    app.inject("route", "myService", "service:myservice");
  },
};

“Services” is a fancy name. But you can imagine a number of practical applications:

Ember’s inject (and corresponding register) methods are pretty powerful. But it's easy to get carried away with dependency injection; keep in mind that just because you are ‘inject’ dependencies doesn't mean you avoid tight-coupling and all the issues that comes with it.

There's a proposal to make services an official convention in Ember.js. You can read more about it here.