Confused about Service vs Factory
Solution 1:
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
Solution 2:
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 runningfn
, in other words:fn()
-
b
’s stored value comes fromnew
ingfn
, in other words:new fn()
-
c
’s stored value comes from first getting an instance bynew
ingfn
, 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.
Solution 3:
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()];
}
Solution 4:
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
Solution 5:
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.