Confused about Service vs Factory
Asked Answered
S

20

630

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, e.g. User is a singleton?

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

Snapback answered 7/12, 2012 at 11:31 Comment(2)
Next to "module.service" and "module.factory" there are 2 more ways to create services in AngularJS. For more info check by blog post: "How to create (singleton) AngularJS services in 4 different ways"Suggestion
Possible duplicate of angular.service vs angular.factoryPase
K
606

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

Kootenay answered 7/12, 2012 at 13:17 Comment(14)
See also #15666548 which discusses the differences between service, factory, and provide.Sporogony
The official doc indirectly[sic! not enought clear] implies that even if you define service with factory, its created only once. In other words its NOT created again as per reference (injection point) -whatever you call it. Both ways result in a singleton instance per injector.Endometriosis
You say "service is just a constructor function that will be called with 'new'" but I think that's misleading. I don't think it's called with new behind the scenes, I think the developer is responsible for calling new on it.Knowles
@nfiniteloop, check the source code near line 3574. Factories are a provider's $get method, and services are generate factories using a method that calls $injector.instantiate on the provided function, which then calls new. (See Docs)Plate
I was under the impression that a service was as singleton that you used by getting a reference to it. And that a factory was a singleton that returned a new object each time. That is, a service would give you one "car" and everything in your project would use this car. While a factory would give you a new car each time you invoked the factory. One was a singleton that returned a singleton and one was a singleton that returned an object. Can anyone explain? Calling everything a singleton doesn't help since it can refer to multiple things.Quadrivalent
Factories don't necessarily need to return an object. It can return whatever you want. Services return the function instance.Adara
of course, the always helpful @johnlindquist eloquently explains services here - egghead.io/lessons/angularjs-providersTalishatalisman
The examples in the slideshow linked in the main question are super useful: slides.wesalvaro.com/20121113/#Too
What does happen if the contents of myService and myFactory are swapped?Coelom
@DeanOr thanks, that's a real difference that anyone has talked about until your comment. +1Kira
"Services return the function instance" should be the constructor function returns a service instance.Desired
Why do you put "you can run some code before" under factory but not service function? Can't you also run some code before this.something?Bill
@Quadrivalent off so many answers, I only like yours regardless it's correct or not, because you used plain English and analogy, rather than lots of concepts/terminologies became endless loop for it self and makes you dizzy. PLAIN ENGLISH please :)Ballance
meanwhile factory is used once when: [ 'bean', 'bean', function (bean1, bean2) { bean1 == bean2 ; } ]Samale
S
389

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:

  1. a's stored value comes from running fn , in other words: fn()
  2. b’s stored value comes from newing fn, in other words: new fn()
  3. c’s stored value comes from first getting an instance by newing 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.

Surname answered 14/11, 2014 at 6:32 Comment(5)
This should be the accepted answer as it actually answers the question of WHY factories, services, and providers return singleton values. The other answers explain the difference between factories, services, and providers but never touch on the singleton aspect.Foil
I like this... When i read the thousand lines of sentence from other blogger.. i only manage to understand factory. But i read this... i understand all 3.Hierarchy
Both .service and .factory are shortcuts for .provide. In the end all services come from calling .$get().Desired
so you must provide a implementation of $get when using providers?Scene
@Scene That is correct. AngularJs docsSnowwhite
N
95

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()];
}​
Nevernever answered 28/10, 2013 at 13:50 Comment(0)
P
57

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

Pyramid answered 9/4, 2013 at 14:39 Comment(5)
I'm having issues with minification using your example. Do you know how i should annotate this?Lied
Yes, there is there exists a minified notation for Angular. It should be something like this: App.factory('MyObjectWithParam', ['$injector', function ($injector) { return function(name) { return $injector.instantiate(MyObjectWithParam,{ name: name }); }; }]); Read more about it here: docs.angularjs.org/tutorial/step_05Pyramid
why would you want to do this, if you can use .service instead?Bratwurst
i had the same thought @flup. @justgoscha, is there some benefit (percieved?) of using .factory as opposed to .service ?Mercola
I think because a service is a singleton. What I constructed here is basically a class which is newable. So you can have something like a Car service factory and then make new Car('BMW') and new Car('Ford') and they don't share the same variables and everything.Pyramid
V
51

Here are the primary differences:

Services

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

Result: When declaring serviceName as an injectable argument you will be provided with the instance of a function 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.

Also check AngularJS documentation and similar question on stackoverflow confused about service vs factory.

Here is example using services and factory. Read more about AngularJS service vs factory.

Virgulate answered 23/12, 2013 at 0:1 Comment(1)
This makes sense to me. The he factory returns the blueprint for creating new objects.Islamize
L
27

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);
    }]);
  }
Leatriceleave answered 20/6, 2013 at 11:35 Comment(0)
L
25

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.

Lordsandladies answered 25/11, 2014 at 14:17 Comment(1)
yes. let's not make things more complicated than they really areBratwurst
L
20

All providers work the same way. The different methods service, factory, provider just let you accomplish the same thing in less code.

P.S. There's also value and constant.

Each special case down the chain starting with provider and ending with value has an added limitation. So to decide between them you have to ask yourself which let's you accomplish what you want with less code.

Here is a picture that shows you what I mean:

enter image description here

You can a breakdown and reference guide on the blog post I got this image from:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

Lacee answered 10/12, 2015 at 13:2 Comment(6)
Services are said to be singleton, but how come it's singleton, if new instance is being created each time i inject it ?Bethel
@AnkurMarwaha A new instance is not created each time, it's only created once and cached by AngularJS. This is true whether you are using a provider, factory, service, etc. You can confirm this using console.log() and injecting into multiple controllers.Lacee
Luis, Your comment conflicts with the accepted answer as it says -- 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.Bethel
@AnkurMarwaha maybe I'm misunderstanding something. You quoted "it is important to realize that all Angular services are application singletons" - the fact that they are singletons means they are only created once. Which is what I said "A new instance is not created each time, it's only created once and cached...". Can you point out in more detail where you see the conflict?Lacee
"This means that there is only one instance of a given service per injector." - From my comment. This means every time I inject it to any controller, a new instance will be created, right? That's what conflicts.Bethel
Ah, I see the confusion. The "injector" is an object in angular. It's in charge of doing the "injection". Example, when the controller is first run the "injector" looks at the parameters and injects each one. There is only one "injector" for your whole app. Once the injector creates a particular factory or service it keeps an instance to it and reuses it - hence the singleton. So there is only one injector per app and only one instance of a given service per injector. Most Angular applications only have one app, therefore one injector, therefore one instance of any service, controller, etc.Lacee
I
13

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
Islamize answered 29/7, 2014 at 7:56 Comment(3)
it's an useful example, number_of_counter_factories is like a meta atrribute of CounterFactory class, right?, I understand this example is replicable on a service (tell me if I'm wrong), what would be the semantic difference in this case?Seducer
Useful example! So this basically means that in a factory you can have that extra layer of abstraction which would wouldn't get in a service. Whatever is returned though, a new instance of it will be returned whenever 'new' is used. Any variables that are not declared inside the return block will be singleton. Did I get it right?Glenoid
@Glenoid basically yes, you can declare variables that are singletons in the factory. That's why I called them "class" variables.Islamize
G
13

“Factory” and “Service” are different ways of doing DI (Dependency injection) in angular.

So when we define DI using “service” as shown in the code below. This creates a new GLOBAL instance of the “Logger” object and injects it in to the function.

app.service("Logger", Logger); // Injects a global object

When you define DI using a “factory” it does not create a instance. It just passes the method and later the consumer internally has to make calls to the factory for object instances.

app.factory("Customerfactory", CreateCustomer);

Below is a simple image which shows visually how DI process for “Service” is different than “Factory”.

enter image description here

Factory should be used When we want to create different types of objects depending on scenarios. For example depending on scenario we want to create a simple “Customer” object , or “Customer” with “Address” object or “Customer” with “Phone” object. Here is a detailed explanation of this paragraph

Service should be used When we have utility or shared functions to be injected like Utility , Logger , Error handler etc.

Gravestone answered 2/4, 2015 at 1:39 Comment(1)
Every answer I've seen on this question and similar others are specifying the difference in mechanics and syntax. This answer gives a real reason why you would select one over the other. It's a matter of semantics and looking at the name, service or factory, communicates their purpose and how they're used.Redingote
C
8

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

Caterinacatering answered 17/12, 2015 at 0:6 Comment(0)
B
2

The basic difference, is that provider allows to set primitive (non-objects), array, or callback function values into the factory declared variable, and thus if returning an object it has to be explicitly declared and returned.

On the other hand a service can only be used to set the service declared variable to an object, thus we can avoid the explicit creation and returning of the objects, while on the other hand it allows usage of the this keyword.

Or in short words "provider is a more generic form while service is limited to objects only".

Blemish answered 21/11, 2014 at 1:9 Comment(0)
V
2

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.

Viglione answered 22/1, 2016 at 22:59 Comment(0)
A
1

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

Alkaline answered 1/5, 2016 at 20:21 Comment(0)
S
1

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

Stein answered 26/6, 2016 at 8:19 Comment(0)
H
1

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."

Hexamethylenetetramine answered 1/7, 2016 at 18:1 Comment(0)
W
1
  • 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.
Wearing answered 29/10, 2016 at 15:24 Comment(0)
F
1

There are three ways of handling business logic in AngularJS: (Inspired by Yaakov's Coursera AngularJS course) which are:

  1. Service
  2. Factory
  3. Provider

Here we are only going to talk about Service vs Factory

SERVICE:

Syntax:

app.js

 var app = angular.module('ServiceExample',[]);
 var serviceExampleController =
              app.controller('ServiceExampleController', ServiceExampleController);
 var serviceExample = app.service('NameOfTheService', NameOfTheService);

 ServiceExampleController.$inject = ['NameOfTheService'] //very important as this protects from minification of js files

function ServiceExampleController(NameOfTheService){
     serviceExampleController = this;
     serviceExampleController.data = NameOfTheService.getSomeData();
 }

function NameOfTheService(){
     nameOfTheService = this;
     nameOfTheService.data = "Some Data";
     nameOfTheService.getSomeData = function(){
           return nameOfTheService.data;
     }     
}

index.html

<div ng-controller = "ServiceExampleController as serviceExample">
   {{serviceExample.data}}
</div>

The main features of Service:

  1. Lazily Instantiated: If the service is not injected it won't be instantiated ever. So to use it you will have to inject it to a module.

  2. Singleton: If it is injected to multiple modules, all will have access to only one particular instance. That is why, it is very convenient to share data across different controllers.

FACTORY

Now let's talk about the Factory in AngularJS

First let's have a look at the syntax:

app.js:

var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);

//first implementation where it returns a function
function NameOfTheFactoryOne(){
   var factory = function(){
      return new SomeService();
    }
   return factory;
}

//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
   var factory = {
      getSomeService : function(){
          return new SomeService();
       }
    };
   return factory;
}

Now using the above two in the controller:

 var factoryOne = NameOfTheFactoryOne() //since it returns a function
 factoryOne.someMethod();

 var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
 factoryTwo.someMethod();

Features of Factory:

  1. This types of services follow the factory design pattern. The factory can be thought of as a central place that creates new objects or methods.

  2. This does not only produce singleton, but also customizable services.

  3. The .service() method is a factory that always produces the same type of service, which is a singleton. There is no easy way to configure it's behavior. That .service() method is usually used as a shortcut for something that doesn't require any configuration whatsoever.

Fiddler answered 27/2, 2017 at 19:23 Comment(0)
U
1

For short and simple explanation refer https://mcmap.net/q/40703/-confused-about-service-vs-factory.

For detailed explanation refer https://mcmap.net/q/40387/-angularjs-service-vs-provider-vs-factory.

Also from angularJs documentation: enter image description here

Uremia answered 30/6, 2017 at 11:50 Comment(0)
L
0

You can understand the difference with this analogy - Consider the difference between a normal function that will return some value and constructor function that will get instantiated using new keyword.So creating factory is just similar to create normal function that will return some value(primitive or an object) whereas creating service is like creating constructor function(OO class) of which we can create instance using new keyword. The only thing to notice is here is that when we use Service method to create services it will automatically create instance of it using dependency injection mechanism supported by AngularJS

Lesley answered 2/9, 2017 at 19:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.