As I understand it, when inside a factory I return a 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?
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
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()];
}
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
Here are the primary differences:
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.
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.
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
b
’s stored value comes from new
ing fn
c
’s stored value comes from first getting an instance by new
ing fn
, and then running a $get
method of the instancewhich 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.
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);
}]);
}
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.
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.
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 () { /* ... */ }
};
});
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.
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
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".
“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”.
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.