简体   繁体   中英

angularjs multiple instances of the same service

Say I want more than one instance of a user service (selectedUser & currentUser), they provide the same functionality. Currently I just get around the problem by creating two services that pull their definition from a local function:

angular.module('myUserModule', [])

.factory('userFactory', ['$http', '$q', function ($http, $q) {
  return function getUser(userId) {
    return new $q(function (resolve) {
      //Gets the user with the provided userId
    }
  }
}])

.value('currentUserId', '')
.value('selectedUserId', '')

.service('currentUserService', ['userFactory', 'currentUserId', User])
.service('selectedUserService', ['userFactory', 'selectedUserId', User]);

function User(userFactory, userId) {
  var self = this;
  var promise = userFactory(userId);
  promise.then(function setUserSuccess(result) {
    self.user = result;
  }
}

Just wondering how other people have approached this problem.

Updated: Just to clarify that I am making use of these services as singletons too.

In an unrelated question the solution ended up using a factory that creates multiple instances:

what is the scope of a service in angularjs?

Use the Factory Pattern.

In essence, if you have a User service, you can use a factory to return a unique instance of the service.

function User(userId, $http) {

    var self = this;    

    $http.get('/api/user/', {userId: userId}).success(function(result) {

        self.details = result.data;
    }):
}

userFactory.$inject = ['$http'];
function userFactory($http) {

    return function(user) {

        return new User(user, $http);
    } 
}
angular.module('app').factory('user', userFactory);

But for this example, you can just use $resource . This is a built in angular factory that returns unique Resource instances.

You can use use your factory as an API to return a collection of objects with getter and setter methods.

You can declare new Factory by using the new keywords. However, it is preferable to encapsulate the creation of an instance into a getter method.

Service

(function(){

  function userFactory($http, $q){

    //Create our userFactory
    function userFactory(num){
      this.num = num;
    };

    //Retrieve some user data for example
    function getUser(id){
      return new $q(function(resolve){
        resolve({id: id, data: [1,2,3,4]});
      });
    }

    //Another method
    function awesome(){
      console.log('Awesome method called by : ' + this.num);
    }

    //Set method by prototyping
    userFactory.prototype.getUser = getUser;
    userFactory.prototype.awesome = awesome;

    return {
      //Use get method to return a new instance of our factory
      get: function(){
        //Pass a random id for our factory
        return new userFactory(Math.ceil(Math.random() * 100));
      }
    }

  }

  angular
    .module('app')
    .factory('UserFactory', userFactory);

})();

The you can create your own instance by using the .get() method :

Controller

(function(){

function Controller($scope, UserFactory) {


  var factoryA = UserFactory.get()
  var factoryB = UserFactory.get();

  console.log('A num instance ' + factoryA.num);
  console.log('B num instance ' + factoryB.num);

  factoryA.getUser(1).then(function(data){
    console.log(data);
  });

  factoryB.awesome();

  console.log('Equality = ' + angular.equals(factoryA, factoryB));

}

angular
.module('app', [])
.controller('ctrl', Controller);

})();


(function(){

function Controller2($scope, UserFactory) {

  var factoryC = UserFactory.get()

  console.log('C num instance ' + factoryC.num);

}

angular
.module('app')
.controller('ctrl2', Controller2);

})();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM