Jagu
Jagu

Reputation: 2561

How to create multiple instances of a service (or, what should I be using instead of a service?)

I'm new to Angular and I think I'm using Services incorrectly.

I have three controllers that use data from a REST backend (using Restangular). The endpoint for each is different but the data structure is identical.

After I get the data, I have to do some simple business logic before it can be used in the page, and I want to cache the data locally. But that means I have three controllers with doubled-up code. Not good.

I'd like to centralise that, and let the controllers just ask for a 'version'. I thought I would create an angular Service that wrapped Restangular, and then create three copies of this, each with a different endpoint, and their own state.

But Services are singletons so I guess that's wrong.

Psuedo code...

..MyDataService(..., dataEndpoint)
{
   ...
   var stuff = []

   construct() {
       this.stuff = Restangular.getData(...)
   }

   getSmallest() {
       return this.stuff.sort(...)
   }       
   getLatest() {
       return this.stuff.sort(...)
   }       
   getBiggest() {
       return this.stuff.sort(...)
   }
}


...RedStuffController()
{
    $scope.data = MyService('/things/redstuff/') 
}
...BlueStuffController()
{
    $scope.data = MyService('/things/blue') 
}
...GreenStuffController()
{
    $scope.data = MyService('/things/green') 
}

What should I be doing?

Upvotes: 2

Views: 600

Answers (2)

Michael Kang
Michael Kang

Reputation: 52867

Services and Factories are singletons - one instance is created and shared among all controllers (and anywhere else its injected). I recommend creating a factory method within your singleton factory/service:

JS

app.factory('MyDataService', function() {
    function Stuff(endpoint) {
       ...
       var stuff = []

       this.construct() {
          stuff = Restangular.getData(...)
       }

       this.getSmallest() {
          return stuff.sort(...)
       }       
       this.getLatest() {
          return stuff.sort(...)
       }       
       this.getBiggest() {
           return stuff.sort(...)
       }
    }
    return  { 
        get: function(endpoint) {
             return new Stuff(endpoint);
        }
    }

});

Controller

app.controller('RedStuffController', function($scope, MyDataService) { 
       $scope.data = MyDataService.get('/things/redstuff');
});

app.controller('BlueStuffController', function($scope, MyDataService) { 
       $scope.data = MyDataService.get('/things/bluestuff');
});

app.controller('GreenStuffController', function($scope, MyDataService) { 
       $scope.data = MyDataService.get('/things/greenstuff');
});

Upvotes: 2

Chandermani
Chandermani

Reputation: 42669

What you can do is use a factory to create a service constructor and return it. It would look something like this.

app.factory('MyService',function(Restangular) {
      function MyService(url) {
          this.stuff = Restangular.getData(url)
      }
      MyService.prototype.getSmallest=function() {
         return this.stuff.sort(...)
      }
      return MyService;   //We are not returning service object but service constructor function 
});

Now in the controller inject it and you can do

$scope.data = new MyService('/things/green').getSmallest();

Upvotes: 4

Related Questions