Confused about Service vs Factory

后端 未结 20 2402
轻奢々
轻奢々 2020-11-22 08:49

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

相关标签:
20条回答
  • 2020-11-22 09:33

    There is also a way to return a constructor function so you can return newable classes in factories, like this:

    function MyObjectWithParam($rootScope, name) {
      this.$rootScope = $rootScope;
      this.name = name;
    }
    MyObjectWithParam.prototype.getText = function () {
      return this.name;
    };
    
    App.factory('MyObjectWithParam', function ($injector) {
      return function(name) { 
        return $injector.instantiate(MyObjectWithParam,{ name: name });
      };
    }); 
    

    So you can do this in a controller, which uses MyObjectWithParam:

    var obj = new MyObjectWithParam("hello"),
    

    See here the full example:
    http://plnkr.co/edit/GKnhIN?p=preview

    And here the google group pages, where it was discussed:
    https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ

    0 讨论(0)
  • 2020-11-22 09:34

    Here are some more examples of services vs factories which may be useful in seeing the difference between them. Basically, a service has "new ..." called on it, it is already instantiated. A factory is not instantiated automatically.

    Basic Examples

    Return a class object which has a single method

    Here is a service that has a single method:

    angular.service('Hello', function () {
      this.sayHello = function () { /* ... */ };
    });
    

    Here is a factory that returns an object with a method:

    angular.factory('ClassFactory', function () {
      return {
        sayHello: function () { /* ... */ }
      };
    });
    

    Return a value

    A factory that returns a list of numbers:

    angular.factory('NumberListFactory', function () {
      return [1, 2, 3, 4, 5];
    });
    
    console.log(NumberListFactory);
    

    A service that returns a list of numbers:

    angular.service('NumberLister', function () {
      this.numbers = [1, 2, 3, 4, 5];
    });
    
    console.log(NumberLister.numbers);
    

    The output in both cases is the same, the list of numbers.

    Advanced Examples

    "Class" variables using factories

    In this example we define a CounterFactory, it increments or decrements a counter and you can get the current count or get how many CounterFactory objects have been created:

    angular.factory('CounterFactory', function () {
      var number_of_counter_factories = 0; // class variable
    
      return function () {
        var count = 0; // instance variable
        number_of_counter_factories += 1; // increment the class variable
    
        // this method accesses the class variable
        this.getNumberOfCounterFactories = function () {
          return number_of_counter_factories;
        };
    
        this.inc = function () {
          count += 1;
        };
        this.dec = function () {
          count -= 1;
        };
        this.getCount = function () {
          return count;
        };
      }
    
    })
    

    We use the CounterFactory to create multiple counters. We can access the class variable to see how many counters were created:

    var people_counter;
    var places_counter;
    
    people_counter = new CounterFactory();
    console.log('people', people_counter.getCount());
    people_counter.inc();
    console.log('people', people_counter.getCount());
    
    console.log('counters', people_counter.getNumberOfCounterFactories());
    
    places_counter = new CounterFactory();
    console.log('places', places_counter.getCount());
    
    console.log('counters', people_counter.getNumberOfCounterFactories());
    console.log('counters', places_counter.getNumberOfCounterFactories());
    

    The output of this code is:

    people 0
    people 1
    counters 1
    places 0
    counters 2
    counters 2
    
    0 讨论(0)
  • 2020-11-22 09:37

    Service style: (probably the simplest one) returns the actual function: Useful for sharing utility functions that are useful to invoke by simply appending () to the injected function reference.

    A service in AngularJS is a singleton JavaScript object which contains a set of functions

    var myModule = angular.module("myModule", []);
    
    myModule.value  ("myValue"  , "12345");
    
    function MyService(myValue) {
        this.doIt = function() {
            console.log("done: " + myValue;
        }
    }
    
    myModule.service("myService", MyService);
    myModule.controller("MyController", function($scope, myService) {
    
        myService.doIt();
    
    });
    

    Factory style: (more involved but more sophisticated) returns the function's return value: instantiate an object like new Object() in java.

    Factory is a function that creates values. When a service, controller etc. needs a value injected from a factory, the factory creates the value on demand. Once created, the value is reused for all services, controllers etc. which need it injected.

    var myModule = angular.module("myModule", []);
    
    myModule.value("numberValue", 999);
    
    myModule.factory("myFactory", function(numberValue) {
        return "a value: " + numberValue;
    })  
    myModule.controller("MyController", function($scope, myFactory) {
    
        console.log(myFactory);
    
    });
    

    Provider style: (full blown, configurable version) returns the output of the function's $get function: Configurable.

    Providers in AngularJS is the most flexible form of factory you can create. You register a provider with a module just like you do with a service or factory, except you use the provider() function instead.

    var myModule = angular.module("myModule", []);
    
    myModule.provider("mySecondService", function() {
        var provider = {};
        var config   = { configParam : "default" };
    
        provider.doConfig = function(configParam) {
            config.configParam = configParam;
        }
    
        provider.$get = function() {
            var service = {};
    
            service.doService = function() {
                console.log("mySecondService: " + config.configParam);
            }
    
            return service;
        }
    
        return provider;
    });
    
    myModule.config( function( mySecondServiceProvider ) {
        mySecondServiceProvider.doConfig("new config param");
    });
    
    myModule.controller("MyController", function($scope, mySecondService) {
    
        $scope.whenButtonClicked = function() {
            mySecondService.doIt();
        }
    
    });
    

    src jenkov

    <!DOCTYPE html>
        <html ng-app="app">
        <head>
        	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
        	<meta charset=utf-8 />
        	<title>JS Bin</title>
        </head>
        <body ng-controller="MyCtrl">
        	{{serviceOutput}}
        	<br/><br/>
        	{{factoryOutput}}
        	<br/><br/>
        	{{providerOutput}}
        
        	<script>
        
        		var app = angular.module( 'app', [] );
        
        		var MyFunc = function() {
        
        			this.name = "default name";
        
        			this.$get = function() {
        				this.name = "new name"
        				return "Hello from MyFunc.$get(). this.name = " + this.name;
        			};
        
        			return "Hello from MyFunc(). this.name = " + this.name;
        		};
        
        		// returns the actual function
        		app.service( 'myService', MyFunc );
        
        		// returns the function's return value
        		app.factory( 'myFactory', MyFunc );
        
        		// returns the output of the function's $get function
        		app.provider( 'myProv', MyFunc );
        
        		function MyCtrl( $scope, myService, myFactory, myProv ) {
        
        			$scope.serviceOutput = "myService = " + myService;
        			$scope.factoryOutput = "myFactory = " + myFactory;
        			$scope.providerOutput = "myProvider = " + myProv;
        
        		}
        
        	</script>
        
        </body>
        </html>

    jsbin

    <!DOCTYPE html>
    <html ng-app="myApp">
    <head>
    	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    	<meta charset=utf-8 />
    	<title>JS Bin</title>
    </head>
    <body>
    <div ng-controller="MyCtrl">
        {{hellos}}
    </div>
    	<script>
    
    	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() {
    
        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()];
    }
    	</script>
    
    </body>
    </html>

    jsfiddle

    0 讨论(0)
  • 2020-11-22 09:38

    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()];
    }​
    
    0 讨论(0)
  • 2020-11-22 09:39

    This is how I understood the difference between them in terms of design patterns:

    Service: Return a type, that will be newed to create an object of that type. If Java analogy is used, Service returns a Java Class definition.

    Factory: Returns a concrete object that can be immediately used. In Java Analogy a Factory returns a Java Object.

    The part that often confuses people (including myself) is that when you inject a Service or a Factory in your code they can be used the same way, what you get in your code in both cases is a concrete object that you can immediately invoke. Which means in case of the Service, angular calls "new" on the service declaration on behalf of you. I think this is a convoluted concept.

    0 讨论(0)
  • 2020-11-22 09:41

    Very simply:

    .service - registered function will be invoked as a constructor (aka 'newed')

    .factory - registered function will be invoked as a simple function

    Both get invoked once resulting in a singleton object that gets injected into other components of your app.

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