AngularJS service inheritance

后端 未结 4 570
北海茫月
北海茫月 2020-12-28 09:14

I have next service:

angular.module(\'app\').service(\'BaseService\', function (alertService) {
   var service = {};
   service.message =  \"Hello\";
   serv         


        
相关标签:
4条回答
  • 2020-12-28 09:27

    I would modify a little bit your code:

    app.factory('BaseService', function () {
       //var service = {}; 
       function service(){
           this.message = "hello";
       }; 
       service.prototype.perform = function () {
            console.log('perfom', this.message);
       };
       return new service();
    });
    

    (I just change your alertService for an console.log();.. )

    then implement inheritance like this:

    app.factory('childBaseService',['BaseService', function(BaseService){
        var childBaseService = function(){
                BaseService.constructor.call(this)
                this.message = 'world!';
        };
    
        childBaseService.prototype = Object.create(BaseService.constructor.prototype);
        childBaseService.prototype.constructor = childBaseService;
    
        return new childBaseService();
    
    }]);
    

    You could see a example of how this works.. at the end, BaseService and childService would be instances of BaseService constructor ( service ).

    console.log(BaseService instanceof BaseService.constructor); //true
    console.log(childBaseService instanceof BaseService.constructor); //true
    
    0 讨论(0)
  • 2020-12-28 09:28

    Here is an example, based on Constructor/new inheritance(which I would generally recommend against).

    BaseService.$inject = ['alertService']
    function BaseService(alertService) {
        this.message = 'hello'
        this.alertService = alertService
    }
    
    BaseService.prototype.perform = function perform() {
        this.alertService.add("success",this.message);
    }
    
    
    ChildService.$inject = ['alertService']
    function ChildService(alertService) {
        this.message = 'hello world'
        this.alertService = alertService
    }
    
    ChildService.prototype = Object.create(BaseService.prototype)
    

    And then you would just include these as services:

    angular.module('app')
        .service('BaseService', BaseService)
        .service('ChildService', ChildService)
    
    0 讨论(0)
  • 2020-12-28 09:38

    AngularJS does not provide any mechanism to implement inheritance of services directly, however for your case you can use $provide.decorator to extend BaseService itself or use it like a prototype of another ChildService using plain JavaScript. In my practice, in order to have service with configurable state and behaviour I use providers. In all of the following examples the console output will be World.

    Decorator

    If you don't need the original BaseService in your module, you can decorate it

    Plunker

    function AlertService() {
      this.add = function(level, message) {
        switch(level) {
          case 'success':
            console.log(message);
        }
      }
    }
    
    function BaseService(alertService) {
      this.message =  "Hello";
      this.perform = function () {
        alertService.add("success",this.message);
      };
    }
    
    angular.
      module('app',[]).
      config(['$provide', function($provide) {
        $provide.decorator('BaseService', function($delegate) {
          $delegate.message = 'World';
          return $delegate;
        });
      }]).
      service('alertService', AlertService).
      service('BaseService', ['alertService',BaseService]).
      controller('ctrl', ['BaseService', function(baseService) {
        baseService.perform();
      }]);
    

    Prototypical Inheritance

    Plunker

    function AlertService() {
      this.add = function(level, message) {
        switch(level) {
          case 'success':
            console.log(message);
        }
      }
    }
    
    function BaseService(alertService) {
      this.message =  "Hello";
      this.perform = function () {
        alertService.add("success",this.message);
      };
    }
    
    function ChildService(BaseService) {
      angular.extend(ChildService.prototype, BaseService);
      this.message = "World";
    }
    
    angular.
      module('app',[]).
      service('alertService', AlertService).
      service('BaseService', ['alertService',BaseService]).
      service('ChildService', ['BaseService',ChildService]).
      controller('ctrl', ['ChildService', function(ChildService) {
        ChildService.perform();
      }]); 
    

    Provider

    Plunker

    function AlertService() {
      this.add = function(level, message) {
        switch(level) {
          case 'success':
            console.log(message);
        }
      }
    }
    
    function BaseService() {
      var message =  "Hello";
    
      this.setMessage = function(msg) {
        message = msg;
      }
    
      function Service(alertService) {
        this.perform = function () {
          alertService.add("success", message);
        };
      }
    
      function Factory(alertService) {
        return new Service(alertService);
      }
    
      this.$get = ['AlertService', Factory];
    }
    
    angular.
      module('app',[]).
      provider('BaseService', BaseService).
      config(['BaseServiceProvider', function(baseServiceProvider) {
        baseServiceProvider.setMessage('World');
      }]).
      service('AlertService', AlertService).
      controller('ctrl', ['BaseService', function(baseService) {
        baseService.perform();
      }]);
    
    0 讨论(0)
  • 2020-12-28 09:47

    Module A with service ASvc:

    (function(angular) {
      var app = angular.module('A', []);
    
      app.service('ASvc', ['$http', function($http) {
         var ASvc = {
           list: function() {
             return $http({
               method: 'GET',
               url: '/A'
             });
           },
    
           getInstructions: function(id) {
             return $http({
               method: 'GET',
               url: '/instructions/' + id
             });
           }
         };
         return ASvc;
      }]);
    })(angular);
    

    Module B with service BSvc which inherits from ASvc:

    (function(angular) {
      var app = angular.module('B', ['A']);
    
      app.service('BSvc', ['$http', 'ASvc', function($http, ASvc) {
         var BSvc = {
           list: function() {
             return $http({
               method: 'GET',
               url: '/B'
             });
           }
         };
    
         BSvc.__proto__ = ASvc; // here you're settting the inheritance
         return BSvc;
      }]);
    })(angular);
    

    Now, when you call BSvc.getInstructions(30775);, you're calling the parent's service (ASvc) getInstructions function from BSvc, and when you call BSvc.list(), you're calling a method which was overridden from ASvc in BSvc. Inheritance.

    And BTW, when I'm passing angular as argument to the closure, instead of referring to the global angular variable directly from within it, I'm allowing code minifiers and obfuscators to do things like this:

    (function(j){var c=j.module('A',[]);})(angular); // and so on
    

    It's a good thing to have in mind and I consider it being a good practice ;)

    0 讨论(0)
提交回复
热议问题