Confused about Service vs Factory

后端 未结 20 2328
轻奢々
轻奢々 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:17

    This would be the best and short answer for understanding Service Vs Factory Vs Provider

    Source: https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/HuZsOsMvKv4J

    Here what ben says with a demo http://jsbin.com/ohamub/1/edit?html,output

    "There are comments in the code illustrating the primary differences but I will expand on them a bit here. As a note, I am just getting my head around this so if I say anything that is wrong please let me know.

    Services

    Syntax: module.service( 'serviceName', function );

    Result: When declaring serviceName as an injectable argument you will be provided the actual function reference passed to module.service.

    Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending () to the injected function reference. Could also be run with injectedArg.call( this ) or similar.

    Factories

    Syntax: module.factory( 'factoryName', function );

    Result: When declaring factoryName as an injectable argument you will be provided the value that is returned by invoking the function reference passed to module.factory.

    Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances.

    Providers

    Syntax: module.provider( 'providerName', function );

    Result: When declaring providerName as an injectable argument you will be provided the value that is returned by invoking the $get method of the function reference passed to module.provider.

    Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances but that requires some sort of configuration before being injected. Perhaps useful for classes that are reusable across projects? Still kind of hazy on this one." Ben

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

    I had this confusion for a while and I'm trying my best to provide a simple explanation here. Hope this will help!

    angular .factory and angular .service both are used to initialize a service and work in the same way.

    The only difference is, how you want to initialize your service.

    Both are Singletons


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


    Factory

    app.factory(<service name>, <function with a return value>)

    If you would like to initialize your service from a function that you have with a return value, you have to use this factory method.

    e.g.

    function myService() {
      //return what you want
      var service = {
        myfunc: function (param) { /* do stuff */ }
      }
      return service;
    }
    
    app.factory('myService', myService);
    

    When injecting this service (e.g. to your controller):

    • Angular will call your given function (as myService()) to return the object
    • Singleton - called only once, stored, and pass the same object.


    Service

    app.service(<service name>, <constructor function>)

    If you would like to initialize your service from a constructor function (using this keyword), you have to use this service method.

    e.g.

    function myService() {
      this.myfunc: function (param) { /* do stuff */ }
    }
    
    app.service('myService', myService);
    

    When injecting this service (e.g. to your controller):

    • Angular will newing your given function (as new myService()) to return the object
    • Singleton - called only once, stored, and pass the same object.


    NOTE: If you use factory with <constructor function> or service with <function with a return value>, it will not work.


    Examples - DEMOs

    • Angular Service vs Factory
    • Angular Service vs Factory (with route)
    0 讨论(0)
  • 2020-11-22 09:17

    This is what helped me to understand the difference, thanks to a blog post by Pascal Precht.

    A service is a method on a module that takes a name and a function that defines the service. You can inject and use that particular service in other components, like controllers, directives and filters. A factory is a method on a module and it also takes a name and a function, that defines the factory. We can also inject and use the it same way we did with the service.

    Objects created with new use the value of the prototype property of their constructor function as their prototype, so I found the Angular code that calls Object.create(), that I believe is the service constructor function when it gets instantiated. However, a factory function is really just a function that gets called, which is why we have to return an object literal for the factory.

    Here is the angular 1.5 code I found for factory:

    var needsRecurse = false;
        var destination = copyType(source);
    
        if (destination === undefined) {
          destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
          needsRecurse = true;
        }
    

    Angular source code snippet for the factory() function:

     function factory(name, factoryFn, enforce) {
        return provider(name, {
          $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
        });
      }
    

    It takes the name and the factory function that is passed and returns a provider with the same name, that has a $get method which is our factory function. Whenever you ask the injector for a specific dependency, it basically asks the corresponding provider for an instance of that service, by calling the $get() method. That’s why $get() is required, when creating providers.

    Here is the angular 1.5 code for service.

    function service(name, constructor) {
        return factory(name, ['$injector', function($injector) {
          return $injector.instantiate(constructor);
        }]);
      }
    

    It turns out that when we call service(), it actually calls factory()! However, it doesn’t just pass our service constructor function to the factory as is. It also passes a function that asks the injector to instantiate an object by the given constructor.

    In other words, if we inject MyService somewhere, what happens in the code is:

    MyServiceProvider.$get(); // return the instance of the service
    

    To restate it again, a service calls a factory, which is a $get() method on the corresponding provider. Moreover, $injector.instantiate() is the method that ultimately calls Object.create() with the constructor function. That’s why we use "this" in services.

    For ES5 it doesn't matter which we use: service() or factory(), it’s always a factory that is called which creates a provider for our service.

    You can do the exact same thing with services as well though. A service is a constructor function, however, that doesn’t prevent us from returning object literals. So we can take our service code and write it in a way that it basically does the exact same thing as our factory or in other words, you can write a service as a factory to return an object.

    Why do most people recommend to use factories over services? This is the best answer I've seen which comes from Pawel Kozlowski's book: Mastering Web Application Development with AngularJS.

    The factory method is the most common way of getting objects into AngularJS dependency injection system. It is very flexible and can contain sophisticated creation logic. Since factories are regular functions, we can also take advantage of a new lexical scope to simulate "private" variables. This is very useful as we can hide implementation details of a given service."

    0 讨论(0)
  • 2020-11-22 09:17
    • With the factory you actually create an object inside of the factory and return it.
    • With the service you just have a standard function that uses the this keyword to define function.
    • With the provider there’s a $get you define and it can be used to get the object that returns the data.
    0 讨论(0)
  • 2020-11-22 09:20

    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

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

    Adding to the first answer, I think .service() is for people who have written their code in more object oriented style(C#/Java) (using this keyword and instantiating object via prototype/Constructor function).

    Factory is for developers who write code which is more natural to javascript/functional style of coding.

    Take a look at the source code of .service and .factory method inside angular.js - internally they all call provider method:

      function provider(name, provider_) {
        if (isFunction(provider_)) {
          provider_ = providerInjector.instantiate(provider_);
        }
        if (!provider_.$get) {
          throw Error('Provider ' + name + ' must define $get factory method.');
        }
        return providerCache[name + providerSuffix] = provider_;
      }
    
      function factory(name, factoryFn) { \
        return provider(name, { $get: factoryFn }); 
      }
    
      function service(name, constructor) {
        return factory(name, ['$injector', function($injector) {
          return $injector.instantiate(constructor);
        }]);
      }
    
    0 讨论(0)
提交回复
热议问题