4

I have made baseService in angular as following.

app.service('baseService', ['$http', function($http) {

        'use strict';
        this.service = "";
        this.load = function(){
            // implement load 
        }
}]);

Now i want other services to extend this service as the implementation of load method will be same for all the services. My derived service will look as follow.

app.service('jobsService', ['baseService', function( baseService ){

    'use strict';

    angular.copy(baseService, this);

    this.service = 'jobs';    

}]);

Here I am using angular.copy(baseService, this); to extend the baseService. Is this a right approach to inherit a service?

Yeasin Hossain
  • 769
  • 2
  • 6
  • 23

4 Answers4

2

Yes... I'd say so.

You're approach is fine and I'd agree that this an appropriate solution for this. More of a best practice question rather than specifics. Here is a fully working example with both the service and factory patterns Angular provides for different development preference

fiddle


angular.module('app', []);

angular.module('app').factory('BaseFactory', [ function() {

    var load = function() {
        console.log('loading factory base');
    }

    return { 'load': load }
}]);

angular.module('app').factory('ChildFactory', ['BaseFactory', function (BaseService) {

  var child = angular.copy(BaseService);

  child.childLoad = function () {
      console.log('loading factory child');
  };

  return child;
}]);

angular.module('app').service('BaseService', [function() {

    this.load = function() {
        console.log('loading service base');
    }
}]);

angular.module('app').service('ChildService', ['BaseService', function(BaseService) {

    angular.copy(BaseService, this);

    this.childLoad = function() {
        console.log('loading service child');
    }
}]);

angular.module('app').controller('ctrl', ['$scope', 'ChildFactory', 'ChildService', function($scope, ChildFactory, ChildService) {

    ChildService.load();       // 'loading service base'
    ChildService.childLoad();  // 'loading service child'
    ChildFactory.load();       // 'loading factory base'
    ChildFactory.childLoad();  // 'loading factory child'
}]);
scniro
  • 16,844
  • 8
  • 62
  • 106
0
   var BaseService = (function () {
      var privateVar = 0;
      return {
        someAwesomeStuff: function () {
          if (privateVar === 42) {
            alert('You reached the answer!');
          }
          privateVar += 1;
        };
      };
    }());

And create child service like this:

var ChildService = Object.create(BaseService);
ChildService.someMoreAwesomeStuff = function () {
  //body...
};

module.factory('ChildService', function () {
  return ChildService;
});

and you can use this ina controller like this:

function MyCtrl(ChildService) {
  ChildService.someAwesomeStuff();
}

reference

Utku Apaydin
  • 162
  • 1
  • 4
0

Here is your solution (extended2Service), and a solution that i usually use (extendedService).

Personally i prefer my solution because i don't made a new istance of that object.

angular.module('app',[])
.controller('mainCtrl', ['$scope', 'baseService', 'extendedService', 'extended2Service', function($scope, baseService, extendedService, extended2Service ){
  $scope.test = 8;
                      
  $scope.resultBase = baseService.addOne($scope.test);                       
  $scope.resultExtended = extendedService.sum($scope.test, 10);
  $scope.result2Extended = extended2Service.sum($scope.test, 10);
  
  console.log(extendedService);
  console.log(extended2Service);
}])
.factory('baseService', function(){
  var baseService = {};
  
  var _addOne = function(n) {
    return n+1;
  };
  
  baseService.addOne = _addOne;
  return baseService;
  
})
.factory('extendedService', ['baseService', function(baseService){
  var extendedService = {};
  
  var _sum = function(a, b){
    for (var i = 0; i < b; i++) {
      a = baseService.addOne(a);
    }
    return a;
  };
  
  extendedService.addOne = baseService.addOne;
  extendedService.sum = _sum;
  
  return extendedService;
    
}])
.factory('extended2Service', ['baseService', function(baseService){
  var extended2Service = angular.copy(baseService);
  
  var _sum = function(a, b){
    for (var i = 0; i < b; i++) {
      a = baseService.addOne(a);
    }
    return a;
  };
  extended2Service.sum = _sum;
  
  return extended2Service;
}]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div ng-app="app" ng-controller="mainCtrl">
  Value: {{test}} <br>
  Base: {{resultBase}} <br>

  resultExtended : {{resultExtended}} <br>
  result2Extended: {{result2Extended}}
<div>
hayatoShingu
  • 418
  • 5
  • 11
0

A simpler and fairly straightforward option will be to use John Resig's Simple JavaScript Inheritance class.

This gives you a more object oriented approach to inheriting/extending classes plus extra functionalities like constructor calls, function overrides etc.

Using your example:

'use strict';

angular.module('app').factory('BaseService', function ($http) {

  var service = Class.extend({ //Class from John Resig's code
    init: function (params) {
      this.params = params;
    },
    load: function (params) {

      return;
    },

  return service;
});

Then to extend/inherit:

angular.module('app').factory('JobService', function (BaseService) {

  var service = BaseService.extend({
    init: function (params) {
      this._super(params);
    }
  });

  return new service;
});
Johnny
  • 276
  • 2
  • 6
  • Is this the RIGHT way to do it though? Because .factory() returns an object literal as such {'hi': function() {}}. Passing a factory copies the instance. A service is only instantiated ONCE so a .service() has this.functionName functionality. How are we to blend service management (as I like the idea of instantiating a service only ONCE to pass around the application) with bonafide class inheritance, a service constructor extending from a base service. That would be nice. – Paul Carlton Apr 29 '15 at 17:55
  • @DataHerder. the JobService .factory() here returns an instance (new service) which is basically same as using.service(). See http://stackoverflow.com/a/15666049/3805741 – Johnny May 18 '15 at 14:57
  • You need a factory for your service to hold a factory, so you're factory can be accessed by your service factory factory factory service factory. :-/ – Paul Carlton May 18 '15 at 17:25
  • What I mean is, doesn't that defeat the whole purpose of factories vs. services? Kinda reminds me of: http://codeofrob.com/entries/you-have-ruined-javascript.html and I like angular. I'm not trying to be mean, I like the idea of using Resig's simple class inheritance with Angular but is it the right way to do it. – Paul Carlton May 18 '15 at 17:35