One of the things that I’ve found is that my Angular services tend to have a lot of duplicate logic in them. The biggest culprit is HTTP calls for CRUD operations. Whether I’m using Restangular, ngResource, or plain ole’ $http, this has been a constant source of un-DRYing in my code. Let’s take a look at using ECMAScript 6’s class and extends to clean up this duplicate code.
We’ll first create a Base class, and put all our shared HTTP calls in there:
class ServiceBase {
constructor ($http) {
'ngInject';
this.$http = $http;
this.resource = "";
}
all() {
return this.$http.get('api/' + this.resource);
}
}
export default ServiceBase;
Then, we’ll make our individual services, and set them as subclasses that inherit from our Base class, using the new extends feature. In this example, we’ll create a service that represent ideas.
import ServiceBase from '../base.service';
class IdeaService extends ServiceBase {
constructor ($http) {
'ngInject';
super($http);
this.resource = "ideas";
}
ideaSpecificThing() {
// does stuff that the base service can't do
}
}
export default IdeaService;
That’s pretty much the gist of it. If you’d like to see an example implementation, complete with routes and a controller, read on.
The next step is to create a routes file where we will resolve the HTTP query:
function routerConfig ($stateProvider, $urlRouterProvider) {
'ngInject';
$stateProvider
.state('ideas', {
url: '/ideas',
templateUrl: 'app/ideas/index.html',
controller: 'IdeaController',
controllerAs: 'ideaCtrl',
resolve: {
ideas(Idea) {
return Idea.all();
}
}
});
$urlRouterProvider.otherwise('/');
}
export default routerConfig;
And then we inject our ideas into our controller:
class IdeaController {
constructor (ideas) {
'ngInject';
this.ideas = ideas;
}
}
export default IdeaController;
And lastly, we import all our class files and load them into our Angular module as services and a controller:
import ServiceBase from '../app/base.service';
import IdeaService from '../app/ideas/idea.service';
import IdeaController from '../app/ideas/idea.controller';
angular.module('ideaLogger', ['ui.router'])
.service('ServiceBase', ServiceBase)
.service('Idea', IdeaService)
.controller('IdeaController', IdeaController)
That’s all folks! Got any ideas of ways I could make it better? I’d love to hear ’em.