Non-Singleton Services in AngularJS Non-Singleton Services in AngularJS angularjs angularjs

Non-Singleton Services in AngularJS


I'm not entirely sure what use case you are trying to satisfy. But it is possible to have a factory return instances of an object. You should be able to modify this to suit your needs.

var ExampleApplication = angular.module('ExampleApplication', []);ExampleApplication.factory('InstancedService', function(){    function Instance(name, type){        this.name = name;        this.type = type;    }    return {        Instance: Instance    }});ExampleApplication.controller('InstanceController', function($scope, InstancedService){       var instanceA = new InstancedService.Instance('A','string'),           instanceB = new InstancedService.Instance('B','object');           console.log(angular.equals(instanceA, instanceB));});

JsFiddle

Updated

Consider the following request for non-singleton services. In which Brian Ford notes:

The idea that all services are singletons does not stop you from writing singleton factories that can instantiate new objects.

and his example of returning instances from factories:

myApp.factory('myService', function () {  var MyThing = function () {};  MyThing.prototype.foo = function () {};  return {    getInstance: function () {      return new MyThing();    }  };});

I would also argue his example is superior due to the fact that you do not have to use the new keyword in your controller. It is encapsulated within the getInstance method of the service.


I don't think we should ever have a factory return a newable function as this begins to break down dependency injection and the library will behave awkwardly, especially for third parties. In short, I am not sure there are any legitimate use cases for non-singleton sevices.

A better way to accomplish the same thing is to use the factory as an API to return a collection of objects with getter and setter methods attached to them. Here is some pseudo-code showing how using that kind of service might work:

.controller( 'MainCtrl', function ( $scope, widgetService ) {  $scope.onSearchFormSubmission = function () {    widgetService.findById( $scope.searchById ).then(function ( widget ) {      // this is a returned object, complete with all the getter/setters      $scope.widget = widget;    });  };  $scope.onWidgetSave = function () {    // this method persists the widget object    $scope.widget.$save();  };});

This is just pseudo-code for looking up a widget by ID and then being able to save changes made to the record.

Here's some pseudo-code for the service:

.factory( 'widgetService', function ( $http ) {  function Widget( json ) {    angular.extend( this, json );  }  Widget.prototype = {    $save: function () {      // TODO: strip irrelevant fields      var scrubbedObject = //...      return $http.put( '/widgets/'+this.id, scrubbedObject );    }  };  function getWidgetById ( id ) {    return $http( '/widgets/'+id ).then(function ( json ) {      return new Widget( json );    });  }  // the public widget API  return {    // ...    findById: getWidgetById    // ...  };});

Though not included in this example, these kinds of flexible services could also easily manage state.


I don't have time right now, but if it will be helpful I can put together a simple Plunker later to demonstrate.


Another way is to copy service object with angular.extend().

app.factory('Person', function(){  return {    greet: function() { return "Hello, I'm " + this.name; },    copy: function(name) { return angular.extend({name: name}, this); }  };});

and then, for example, in your controller

app.controller('MainCtrl', function ($scope, Person) {  michael = Person.copy('Michael');  peter = Person.copy('Peter');  michael.greet(); // Hello I'm Michael  peter.greet(); // Hello I'm Peter});

Here is a plunk.