Let's say I have a provider named lookup. It's used like this:
.controller('lookupCtrl', ['lookup', function(lookup) {
this.values = lookup('monkey');
}]);
What is lookup? Is it a service()? Is it a factory()? A value()?
In this particular case it can be any of those.
lookup could be a value if you created a regular, plain-old JavaScript object and then used the Value provider, naming your object "lookup". Even though a value is typically a simple type, it could be an object, and this would work.
lookup could also be a factory if you used the factory provider, in which case, you specify a function which returns an object. The object you return is the exact same object that's injected in any routine like the above that requests 'lookup'
And finally, lookup can also be an angular service. If you did that, the service provider would specify a function that returns a "newable" object. So the thing you return will be a function which Angular will "new", and the result of that will be passed to anyone who requests a 'lookup' instance. Note that, even in this case, Angular instantiates your service one and only one time. The difference between factory and service is subtle. Think of a service returning a "class" that angular instantiates once and reuses that one instance. And a factory uses the object that you returned to angular.
The answer is "D: All of the above"
As a service:
.service('myService', function(){
return function(someParam){
console.log(someParam);
};
});
As a factory:
.factory('myFactory', function(){
return function(someParam){
console.log(someParam);
};
});
As a value:
.value('myValue', function(){
console.log(arguments);
});
Here is a Plunkr... look at the console output.
Related
I have such working code:
Service (factory?):
myApp.factory('MyService', ['$q','$resource', 'MyResource',
function ($q, $resource, MyResource) {
return {
getRoles: function () {
return MyResource.getRoles(); //MyResource makes API calls using $resource
} } });
Controller:
$scope.Roles = MyService.getRoles();
$scope.Roles.$promise.then(function () { $scope.RolesCount = $scope.Roles.length; });
What I'd like to do is to create such function in MyService that will return number of roles once getRoles is resolved so I can use it in controller like this:
$scope.RolesCount = MyService.getRolesCount();
and then in html
{{RolesCount}}
Unfortunately, I have no idea how to do this since my getRolesCount() method needs to return something so I can't use $promise.then() inside MyService. I'll try to update my question's title once I come up with something more accurate.
If server response needs to be transformed in a service, then then should be moved there. However, it's not practical or possible if then is supposed to unwrap a promise and assign a value to scope, like in the code above.
$resource returns an object that is filled on promise resolution. The way a resource is supposed to be used in view is:
{{Roles.length}}
When an object is updated, it will be updated in view, too. Assigning the value to another variable is inefficient.
It's impossible to do something like
$scope.RolesCount = MyService.getRolesCount();
because getRolesCount is asynchronous, and the value it resolves with is scalar. It is possible to flatten it with `async..await, (TypeScript or ES2017), but will require additional measures to synchronize control flow with AngularJS digests, as explained in this answer.
I think I had the misconception before that an AngularJS factory is for object creation or functions, while an AngularJS service is for HTTP requests.
Another question talked about this, but it didn't clarify some of the most fundamental concepts.
It looks like their end result is exactly the same -- to get a what is called a "service object". We can usually use factory() or service() interchangeably, and it just matter how the service object is created.
In the case of a factory, the object is returned as is:
angular.module("myApp", [])
.factory("myService", function() {
return { // the awesome service object
foo: 123,
doSomething: function() { }
};
});
In the case of a service, AngularJS will use that function as a contructor function, with a new keyword, to create the service object and return to the user, when the user uses myService.doSomething() or myService.foo in the user's code.
angular.module("myApp", [])
.service("myService", function() {
// I am the awesome service object when AngularJS uses
// the keyword "new" on the above anonymous function.
// "this" will point to myself.
this.foo = 123;
this.doSomething = function() { };
});
So an AngularJS factory or service can actually both do exactly the same thing (such as fetching data from the server), but they just differ how the service object is created.
If we just use the usual, simple JavaScript object literal, we can just use factory(), but the only case we would use service() instead is that, if we want to create a base class, and then use inheritance to create subclasses, and now we have these constructor functions, and to use constructors, we have to use service().
Is this concept correct for AngularJS?
I have gone through lots of document and also refereed stack overflow post regarding this issue.
I am still having confusion When to use Service and Factory.
Can any one Explain using Real World Example when to use what ?
Common thing about service & factory is they are singleton objects,
there instance gets created once per application.
Basically angular service does return an object by using new keyword, whether factory does return an object which you have created.
Service
app.service('myService', function(){
this.myMethod = function(){
return 'something';
};
})
In above service we added one method myMethod which can be available to the the component whoever inject the service. Service does gives access to all of its properties which are assigned to its this context.
Factory
app.factory('myService', function(){
//here you can do some initial work before creating an service object.
//which is very advantageous part of service.
var configuredVariable = 'configured';
return {
myMethod : function(){
return 'something'+ configuredVariable;
};
}
})
You could have controller over object before creating it, you could do some configuration kind of setting before returning an object from a service.
More detailed answer here
Summary
When to Use service and When to factory in agularJS?
Used service whenever you don't won't to return an configurable object, If you want to configure the object you should go for an factory.
I am new to angularJS and going through angular docs.I came across this line controllers are created using a factory function
I tried to find what that means and found what is factory and service and providers but that does not fit here.
How controllers are created using a factory function?
Please explain what is the meaning of factory in this context.
The key quote you are missing from the previous section you are referring to is this:
"First, there is a new JavaScript file that contains a so-called "controller". More exactly, the file contains a constructor function that creates the actual controller instance. "
If this were an actual angular factory, it would make more sense. But, controllers are instances just like Angular factories, services, and providers.
A factory, is actually a Javascript design pattern, maybe reading here it will make more sense.
For the controller to work, the instance must exist for the two-way binding to be able to take place. So basically, an instance of the controller is created. The angular controller page explains it well with:
"When a Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be available as an injectable parameter to the Controller's constructor function as $scope." Here's the link.
In the event of controllers though, you would most likely store items on the $scope and not 'this'. So they separate controllers from factories this way as they do not return an accessible instance of themselves and instead bind their properties to the view through $scope or 'this'.
TO BE CLEAR, I'm not saying that they are referring to Angular factories. I believe the reason for this phrasing is tied to the same wording for the service factory function:
"Application developers are free to define their own services by registering the service's name and service factory function, with an Angular module.
The service factory function generates the single object or function that represents the service to the rest of the application. The object or function returned by the service is injected into any component (controller, service, filter or directive) that specifies a dependency on the service."
They give this example:
var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
So when you see them say created from a factory function, they are just saying using the following pattern:
.controller('PersonCtrl', [
'PersonFactory'
function(PersonFactory) {
this.name = 'Tom';
console.log(PersonFactory.name); //would print 'Tom'
}]);
.factory("PersonFactory", [
function () {
return {
name: 'Tom'
};
}]);
I hope that helps, or maybe someone could be more concise in my explanation and edit this description.
What this means is that you provide AngularJS with a function that it can execute as many times as it needs to produce instances of your controller. So to take the example from the page you linked to:
angular.module('invoice3', ['finance3'])
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
this.qty = 1;
this.cost = 2;
this.inCurr = 'EUR';
this.currencies = currencyConverter.currencies;
this.total = function total(outCurr) {
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
};
this.pay = function pay() {
window.alert("Thanks!");
};
}]);
That function that starts on line 2 with function(currencyConverter) { is the factory function.
Whenever the page has a location that uses an InvoiceController, AngularJS will (essentially) do the following with that factory function, passing in any dependencies that it has:
var currencyConverter = ...; // obtain a currency converter from the factory
var theController = new thatFactoryFunction(currencyConverter);
and then it will use the value that is returned as your controller. It will do this separately for each InvoiceController indicagted the page, creating a separate instance for each one.
(I stress that the code above is purely an illustration of what AngularJS is doing and not an actual representation of the code that it uses.)
The creation of a controller instance is interesting. One would expect that it is created with new InvoiceController(...), and it's also suggested by the sentence More exactly, the file contains a constructor function that creates the actual controller instance, but that's not the case. Actually it's created like this:
instance = Object.create(controllerPrototype);
and later the constructor function is called as function:
return fn.apply(self, args); //self == instance
To be honest, we can only guess what the author meant by factory function. It could be the fact that controllers are not created by new. Maybe the the constructor function is therefore referred to as factory or it's the internal factory function. It could also just be bad wording or even a mistake.
I want to inject instances of a class. From this thread it looks like services return new serviceArgFunction, which is what I want. https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/VxECXKbn3gsJ
But I can't seem to get it to work. For some reason, my two instances of share state. Can anyone help me figure out what I'm doing wrong?
http://jsfiddle.net/kTjMy/5/
var Klass = function() {
this.count = 0;
this.getAndIncCount = function() {
this.count += 1;
return this.count;
};
};
app.service('service', Klass);
You can use a factory that returns the constructor for your class:
app.factory('myKlass', function() {
return Klass
});
Even more simply, if Klass is defined elsewhere, you can use value:
app.value('myKlass', Klass);
Either way, inject it as normal.
function CtrlA($scope, myKlass)
{
new myKlass();
}
See this jsFiddle.
[Edit] See also this Google Groups post and this associated example.
To make it clear I created a little Plunker.
It has a Service and a Factory.
Service and Factory have a value and setters and getters.
Both are injected into Controllers A and B.
If You change the value of the Service in Controller A, this change takes also place in Controller B, because the service is a Singleton.
But when You change the value in the Factory in the Controller B, this affects only B because the change takes only place in the instance that is created in B.
Enjoy!
Maximilian - thank you for the great example.
I converted this to JSFiddle, as a place to experiment with another design pattern that I wanted to dig into.
Why is it that swapping the provider type from "service" to "factory" still seems to work?
It seems more about how the provider is created i.e. using 'new' versus just referencing it directly.
Also, within the service, is there a design pattern as to why a service should implement the "this" keyword, as opposed to using using return { myAccessor : function () { return val; } }
See
http://jsfiddle.net/jeffsteinmetz/XF69p/
In this jsfiddle, you can change one line of the code (line 23), and it still works, the line of code can be either:
App.service('MyService', function() {
or
App.factory('MyService', function() {
Why do these both work?
It seems more about how you reference the service with "new"
var myInstance = new MyFactory();
Which is different than just calling it directly
MyService.getVal()
Any angular folks care to lay out the best practices and reasoning behind this:
when to use 'new' and when you don't need new
why use the 'this' reference approach to define your provider instead of return { accessorName : function}
why do both factory or service work in the above example?