Confused about Service vs Factory

As I understand it, when inside a factory I return an object that gets injected into a controller. When inside a service I am dealing with the object using this and not returning anything.

I was under the assumption that a service was always a singleton, and that a new factory object gets injected in every controller. However, as it turns out, a factory object is a singleton too?

Example code to demonstrate:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

When changing user.first in ACtrl it turns out that user.first in BCtrl is also changed, eg User is a singleton?

My assumption was that a new instance was injected in a controller with a factory?


All angular services are singletons :

Docs (see Services as singletons): https://docs.angularjs.org/guide/services

Lastly, it is important to realize that all Angular services are application singletons. This means that there is only one instance of a given service per injector.

Basically the difference between the service and factory is as follows:

app.service('myService', function() {

  // service is just a constructor function
  // that will be called with 'new'

  this.sayHello = function(name) {
     return "Hi " + name + "!";
  };
});

app.factory('myFactory', function() {

  // factory returns an object
  // you can run some code before

  return {
    sayHello : function(name) {
      return "Hi " + name + "!";
    }
  }
});

Check out this presentation about $provide: http://slides.wesalvaro.com/20121113/#/

Those slides were used in one of the AngularJs meetups: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html


For me the revelation came when I realise that they all work the same way: by running something once , storing the value they get, and then cough up that same stored value when referenced through Dependency Injection.

Say we have:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

The difference between the three is that:

  • a 's stored value comes from running fn , in other words: fn()
  • b 's stored value comes from new ing fn , in other words: new fn()
  • c 's stored value comes from first getting an instance by new ing fn , and then running a $get method of the instance
  • which means, there's something like a cache object inside angular, whose value of each injection is only assigned once, when they've been injected the first time, and where:

    cache.a = fn()
    cache.b = new fn()
    cache.c = (new fn()).$get()
    

    This is why we use this in services, and define a this.$get in providers.

    Hope this helps.


    live example

    " hello world " example

    with factory / service / provider :

    var myApp = angular.module('myApp', []);
    
    //service style, probably the simplest one
    myApp.service('helloWorldFromService', function() {
        this.sayHello = function() {
            return "Hello, World!"
        };
    });
    
    //factory style, more involved but more sophisticated
    myApp.factory('helloWorldFromFactory', function() {
        return {
            sayHello: function() {
                return "Hello, World!"
            }
        };
    });
    
    //provider style, full blown, configurable version     
    myApp.provider('helloWorld', function() {
        // In the provider function, you cannot inject any
        // service or factory. This can only be done at the
        // "$get" method.
    
        this.name = 'Default';
    
        this.$get = function() {
            var name = this.name;
            return {
                sayHello: function() {
                    return "Hello, " + name + "!"
                }
            }
        };
    
        this.setName = function(name) {
            this.name = name;
        };
    });
    
    //hey, we can configure a provider!            
    myApp.config(function(helloWorldProvider){
        helloWorldProvider.setName('World');
    });
    
    
    function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
        $scope.hellos = [
            helloWorld.sayHello(),
            helloWorldFromFactory.sayHello(),
            helloWorldFromService.sayHello()];
    }​
    
    链接地址: http://www.djcxy.com/p/2184.html

    上一篇: angular.service vs angular.factory

    下一篇: 对服务vs工厂感到困惑