$resource; how to encapsulate API methods - javascript

I have following angularjs service that exposes some methods to execute REST requests.
managerApp.factory('parameterService',
function($resource){
return {
findAll: $resource('rest/globalparam/list'),
getByName: $resource('rest/globalparam/getByName/?name=:name'),
update: $resource('rest/globalparam')
};
}
);
This is used as following:
$scope.parameters = parameterService.findAll.query();
$scope.selectedParameter = parameterService.getByName.get({name: $routeParams.id});
Although this works fine I'm not so happy about both the syntax and the fact that I need to know about the $resource API (query(), get()) in my controller. What I would like to see in my controller is:
$scope.parameters = parameterService.findAll();
$scope.selectedParameter = parameterService.getByName($routeParams.id);
This would make unit testing (mocking the service) a lot easier as well.
This is probably more a JavaScript than an AngularJS question.
Is this possible and how?

what you can do differently is to return functions from factory instead of a promise/resource object
managerApp.factory('parameterService',['$resource',
function($resource){
var findAll = function(){return $resource('rest/globalparam/list').query(); }
return {
findAll : findAll
};
}]
);

Related

When should I use factory or service in angular? [duplicate]

Please bear with me here. I know there are other answers such as:
AngularJS: Service vs provider vs factory
However I still can't figure out when you'd use service over factory.
From what I can tell factory is commonly used to create "common" functions that can be called by multiple Controllers: Creating common controller functions
The Angular docs seem to prefer factory over service. They even refer to "service" when they use factory which is even more confusing! http://docs.angularjs.org/guide/dev_guide.services.creating_services
So when would one use service?
Is there something that is only possible or much easier done with service?
Is there anything different that goes on behind the scenes? Performance/memory differences?
Here's an example. Other than the method of declaration, they seem identical and I can't figure out why I'd do one vs the other. http://jsfiddle.net/uEpkE/
Update: From Thomas' answer it seems to imply that service is for simpler logic and factory for more complex logic with private methods, so I updated the fiddle code below and it seems that both are able to support private functions?
myApp.factory('fooFactory', function() {
var fooVar;
var addHi = function(foo){ fooVar = 'Hi '+foo; }
return {
setFoobar: function(foo){
addHi(foo);
},
getFoobar:function(){
return fooVar;
}
};
});
myApp.service('fooService', function() {
var fooVar;
var addHi = function(foo){ fooVar = 'Hi '+foo;}
this.setFoobar = function(foo){
addHi(foo);
}
this.getFoobar = function(){
return fooVar;
}
});
function MyCtrl($scope, fooService, fooFactory) {
fooFactory.setFoobar("fooFactory");
fooService.setFoobar("fooService");
//foobars = "Hi fooFactory, Hi fooService"
$scope.foobars = [
fooFactory.getFoobar(),
fooService.getFoobar()
];
}
Explanation
You got different things here:
First:
If you use a service you will get the instance of a function ("this"
keyword).
If you use a factory you will get the value that is returned by
invoking the function reference (the return statement in factory).
ref: angular.service vs angular.factory
Second:
Keep in mind all providers in AngularJS (value, constant, services, factories) are singletons!
Third:
Using one or the other (service or factory) is about code style.
But, the common way in AngularJS is to use factory.
Why ?
Because "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."
(ref: http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821).
Usage
Service : 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.
Factory : Could be useful for returning a ‘class’ function that can then be new`ed to create instances.
So, use a factory when you have complex logic in your service and you don't want expose this complexity.
In other cases if you want to return an instance of a service just use service.
But you'll see with time that you'll use factory in 80% of cases I think.
For more details: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/
UPDATE :
Excellent post here :
http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html
"If you want your function to be called like a normal function, use
factory. If you want your function to be instantiated with the new
operator, use service. If you don't know the difference, use factory."
UPDATE :
AngularJS team does his work and give an explanation:
http://docs.angularjs.org/guide/providers
And from this page :
"Factory and Service are the most commonly used recipes. The only difference between them is that Service recipe works better for objects of custom type, while Factory can produce JavaScript primitives and functions."
allernhwkim originally posted an answer on this question linking to his blog, however a moderator deleted it. It's the only post I've found which doesn't just tell you how to do the same thing with service, provider and factory, but also tells you what you can do with a provider that you can't with a factory, and with a factory that you can't with a service.
Directly from his blog:
app.service('CarService', function() {
this.dealer="Bad";
this.numCylinder = 4;
});
app.factory('CarFactory', function() {
return function(numCylinder) {
this.dealer="Bad";
this.numCylinder = numCylinder
};
});
app.provider('CarProvider', function() {
this.dealerName = 'Bad';
this.$get = function() {
return function(numCylinder) {
this.numCylinder = numCylinder;
this.dealer = this.dealerName;
}
};
this.setDealerName = function(str) {
this.dealerName = str;
}
});
This shows how the CarService will always a produce a car with 4 cylinders, you can't change it for individual cars. Whereas CarFactory returns a function so you can do new CarFactory in your controller, passing in a number of cylinders specific to that car. You can't do new CarService because CarService is an object not a function.
The reason factories don't work like this:
app.factory('CarFactory', function(numCylinder) {
this.dealer="Bad";
this.numCylinder = numCylinder
});
And automatically return a function for you to instantiate, is because then you can't do this (add things to the prototype/etc):
app.factory('CarFactory', function() {
function Car(numCylinder) {
this.dealer="Bad";
this.numCylinder = numCylinder
};
Car.prototype.breakCylinder = function() {
this.numCylinder -= 1;
};
return Car;
});
See how it is literally a factory producing a car.
The conclusion from his blog is pretty good:
In conclusion,
---------------------------------------------------
| Provider| Singleton| Instantiable | Configurable|
---------------------------------------------------
| Factory | Yes | Yes | No |
---------------------------------------------------
| Service | Yes | No | No |
---------------------------------------------------
| Provider| Yes | Yes | Yes |
---------------------------------------------------
Use Service when you need just a simple object such as a Hash, for
example {foo;1, bar:2} It’s easy to code, but you cannot instantiate
it.
Use Factory when you need to instantiate an object, i.e new
Customer(), new Comment(), etc.
Use Provider when you need to configure it. i.e. test url, QA url,
production url.
If you find you're just returning an object in factory you should probably use service.
Don't do this:
app.factory('CarFactory', function() {
return {
numCylinder: 4
};
});
Use service instead:
app.service('CarService', function() {
this.numCylinder = 4;
});
The concept for all these providers is much simpler than it initially appears. If you dissect a provider you and pull out the different parts it becomes very clear.
To put it simply each one of these providers is a specialized version of the other, in this order: provider > factory > value / constant / service.
So long the provider does what you can you can use the provider further down the chain which would result in writing less code. If it doesn't accomplish what you want you can go up the chain and you'll just have to write more code.
This image illustrates what I mean, in this image you will see the code for a provider, with the portions highlighted showing you which portions of the provider could be used to create a factory, value, etc instead.
(source: simplygoodcode.com)
For more details and examples from the blog post where I got the image from go to: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
Both the factory and the service result in singleton objects which are able to be configured by providers and injected into controllers and run blocks. From the point of view of the injectee, there is absolutely no difference whether the object came from a factory or a service.
So, when to use a factory, and when to use a service? It boils down to your coding preference, and nothing else. If you like the modular JS pattern then go for the factory. If you like the constructor function ("class") style then go for the service. Note that both styles support private members.
The advantage of the service might be that it's more intuitive from the OOP point of view: create a "class", and, in conjunction with a provider, reuse the same code across modules, and vary the behavior of the instantiated objects simply by supplying different parameters to the constructor in a config block.
There is nothing a Factory cannot do or does better in comparison with a Service. And vice verse. Factory just seems to be more popular. The reason for that is its convenience in handling private/public members. Service would be more clumsy in this regard.
When coding a Service you tend to make your object members public via “this” keyword and may suddenly find out that those public members are not visible to private methods (ie inner functions).
var Service = function(){
//public
this.age = 13;
//private
function getAge(){
return this.age; //private does not see public
}
console.log("age: " + getAge());
};
var s = new Service(); //prints 'age: undefined'
Angular uses the “new” keyword to create a service for you, so the instance Angular passes to the controller will have the same drawback.
Of course you may overcome the problem by using this/that:
var Service = function(){
var that = this;
//public
this.age = 13;
//private
function getAge(){
return that.age;
}
console.log("age: " + getAge());
};
var s = new Service();// prints 'age: 13'
But with a large Service constant this\that-ing would make the code poorly readable.
Moreover, the Service prototypes will not see private members – only public will be available to them:
var Service = function(){
var name = "George";
};
Service.prototype.getName = function(){
return this.name; //will not see a private member
};
var s = new Service();
console.log("name: " + s.getName());//prints 'name: undefined'
Summing it up, using Factory is more convenient. As Factory does not have these drawbacks. I would recommend using it by default.
Even when they say that all services and factories are singleton, I don't agree 100 percent with that. I would say that factories are not singletons and this is the point of my answer. I would really think about the name that defines every component(Service/Factory), I mean:
A factory because is not a singleton, you can create as many as you want when you inject, so it works like a factory of objects. You can create a factory of an entity of your domain and work more comfortably with this objects which could be like an object of your model. When you retrieve several objects you can map them in this objects and it can act kind of another layer between the DDBB and the AngularJs model.You can add methods to the objects so you oriented to objects a little bit more your AngularJs App.
Meanwhile a service is a singleton, so we can only create 1 of a kind, maybe not create but we have only 1 instance when we inject in a controller, so a service provides more like a common service(rest calls,functionality.. ) to the controllers.
Conceptually you can think like services provide a service, factories can create multiple instances(objects) of a class
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.
Can use both the way you want : whether create object or just to access functions from both
You can create new object from service
app.service('carservice', function() {
this.model = function(){
this.name = Math.random(22222);
this.price = 1000;
this.colour = 'green';
this.manufacturer = 'bmw';
}
});
.controller('carcontroller', function ($scope,carservice) {
$scope = new carservice.model();
})
Note :
service by default returns object and not constructor function .
So that's why constructor function is set to this.model property.
Due to this service will return object,but but but inside that object will be constructor function which will be use to create new object;
You can create new object from factory
app.factory('carfactory', function() {
var model = function(){
this.name = Math.random(22222);
this.price = 1000;
this.colour = 'green';
this.manufacturer = 'bmw';
}
return model;
});
.controller('carcontroller', function ($scope,carfactory) {
$scope = new carfactory();
})
Note :
factory by default returns constructor function and not object .
So that's why new object can be created with constructor function.
Create service for just accessing simple functions
app.service('carservice', function () {
this.createCar = function () {
console.log('createCar');
};
this.deleteCar = function () {
console.log('deleteCar');
};
});
.controller('MyService', function ($scope,carservice) {
carservice.createCar()
})
Create factory for just accessing simple functions
app.factory('carfactory', function () {
var obj = {}
obj.createCar = function () {
console.log('createCar');
};
obj.deleteCar = function () {
console.log('deleteCar');
};
});
.controller('MyService', function ($scope,carfactory) {
carfactory.createCar()
})
Conclusion :
you can use both the way you want whether to create new object or
just to access simple functions
There won't be any performance hit , using one over the other
Both are singleton objects and only one instance is created per app.
Being only one instance every where their reference is passed.
In angular documentation factory is called service and also service is called service.
Factory and Service are the most commonly used method. The only difference between them is that the Service method works better for objects that need inheritance hierarchy, while the Factory can produce JavaScript primitives and functions.
The Provider function is the core method and all the other ones are just syntactic sugar on it. You need it only if you are building a reusable piece of code that needs global configuration.
There are five methods to create services: Value, Factory, Service, Provider and Constant. You can learn more about this here angular service, this article explain all this methods with practical demo examples.
.

How not to use 'this' in Angular?

New to Angular and I'm trying to follow JSLint ( written by Douglas Crockford ) recommendation of not using this in JS at all.
How can I prevent myself to use this in Angular? All the tutorials I've seen so far rely on using this and SO search had resulted in no answer.
For the purpose of being clear, let's assume I'm trying to write this controller:
app.controller('StoreController', function() {
this.products = {};
});
How can I access the controller object so I can add the products property?
var my_controller = app.controller('StoreController', function() {
});
my_controller.products = {}; // Maybe like this?
Inject $scope, for example:
app.controller('StoreController', function($scope) {
$scope.products = {};
});
Here is more information about them: https://docs.angularjs.org/guide/scope
Also, when using things like services, you can avoid this by keeping a local state and returning an interface object. For example:
.service('MyService', function(){
// state
var mystate = {};
// interface object
return {
someExposedFunc: function(){
}
};
});
I would just like to note though, that I don't see any good reason why you should avoid this when using angular. I think using $scope has more semantic usefulness when reading controller code, but when using things like services, I write less code by creating exposed functions like this.somefunc = ....

Injecting service which define by module.provider

Sorry to ask something like this, but i m already spend couple of days to solve this one.
But i m really need help. I am already read Understanding Dependency Injection
and also other stack question use $http inside custom provider in app config use the
$injector
on run block also not work in my code.
Perhaps someone here can help me, i am also worried how annotate the injection on my provider for minification.
My code in
Here
The problem is that when you call $http in the _getItem you are in the "controller". A solution could be to do this:
this.$get = function($http) {
return {
mainUrl : _mainUrl,
getItem : _getItem,
httpWrapper : $http
};
And then in the _getItem assign (or use the httpWrapper directly):
var $http = this.httpWrapper;
In order to avoid problems with the minification, you could add the injection to the method $get:
this.$get = ['$http', function($http) {
Here the updated Plunker: http://plnkr.co/edit/m7oXNolo6iV8Zy1NJ0vx
EDIT: I think that what you wanted to achieve is this:
var _getItem = function() {
var _d = null;
console.log(this)
var $http = this.httpWrapper;
var $q = this.qWrapper;
_d = $q.defer();
$http.get(_mainUrl)
.success(function(data) {
console.log(data);
_d.resolve( {data: data, x: "efe"} );
})
.error(function(status) {
_d.resolve( status );
});
return _d.promise;
};
$q.defer() allows to defer the http call to your controller, then on your controller you have to edit this:
facade.getItem().then(function(data){
$scope.myReturn = data;
}
Updated Plunker: http://plnkr.co/edit/xR1d3KnWhX51jHHZ8t3m
Note: Consider that the nature of then is asynchronous, thus if you use the variable straight afterwards, it still will be undefined

service vs controller vs external js to put frequently used methods in angularjs

I have an angularjs app, which has several controllers with several viewes. When I started coding the app there were few methods(of similar kind), which were used in more than places, initially it looked OK to me to put those methods where ever needed (two or three controllers). But as my application grew I started noticing the code redundancy issue, as the method was required at more places.
Definitely this was my lack of experience which lead to this issue.
Now I decided to remove this redundant code from my app. I found the following options:
Service way: Remove the redundant code and put it in a new service and include the service all the places where I need the functionality.
External JS: Putting the redundant code in an external js file and just call the required method.
Leave the code as it is.
But here I want to mention that the redundant code I am talking is not very tight coupled and can be added and removed any where with a very little effort.
Now, what I want to know is from the above options, which one should I choose? OR are there much better options available for this issue(may be provided by angularJS itself).
Edit Basic examples of code:as I said
$scope.showSomething = function (show, ele) {
//show or hide the ele (element) based on value of show
}
You are using angular so surely you want to make your app structured according to MVC. what kind of MVC pattern your app will follow if your code is put anywhere in a js file like anything. I would recommend putting your code inside a service. that's the angular way of reducing redundancy. Also you have another option to set the function to the $rootscope here
I'm not sure about your case, but I had similar situation: I had a number of functions which provide validation functionality. I created service:
'use strict';
angular.module('myApp')
.factory('UtilService', ['Env', 'IBANChecker', function(Env, IBANChecker) {
var validateCallbacks = {
checkAddress: function (address) {
return address.action != 'delete';
},
validateIBAN: function (iban) {
return !iban || IBANChecker.isValid(iban);
},
.....
validateYCode: function(id) {
return YCodeChecker.isValid(id);
}
};
return {
/**
* Factory with callbacks for 'validate' directive.
* 0 arguments -- get all callbacks, over wise see #validateCallbacks object to get specific callbacks.
* if wrong callback name requested -> it will be ignored
* #returns {object} -- call requested callbacks.
*/
getValidateCallbacks : function() {
if(arguments.length) {
var result = {};
_.each(arguments, function(argument){
if(validateCallbacks[argument]) {
result[argument] = validateCallbacks[argument];
}
});
return result;
} else {
return validateCallbacks;
}
}
};
}]);
And code in controller looks like:
var validateCallbacks = UtilService.getValidateCallbacks('validateText', 'validateNumber');
_.each(validateCallbacks, function(callback, key) {
$scope[key] = callback;
});
I tend to use factories, specifically because factories can depend on other factories and logical modules can be defined. Consider the psuedo code below.
.controller('HisController', function (UtilityService) {
$scope.foo = UtilityService.foo;
})
.controller('HerController', function (UtilityService) {
$scope.foo = UtilityService.foo;
})
.factory('UtilityService', function (SomeOtherService) {
var service = {
foo: foo,
bar: bar,
}
return service
///////
function foo(a) {
return a.substring(0,1);
}
function bar(a) {
return SomeOtherService.doStuff(service.foo(a));
}
})

AngularJS learning about services and factories, a service in a factory?

I'm really trying to wrap my head around angular's service/factory/provider constructs before I refactor a pretty big project.
I've read lots of docs and articles on services vs. factories and thought I understood how each of them are created and what they do.
However, while trying stuff I attempted to use a service in a factory or two...
This was really useful: I now understand that there is only one of my 'jsonService' (it's a singleton), so this simple approach WILL NOT WORK... (I'll need each factory to have a separate instance of something)
.service('jsonService', ['$http', function ($http) {
var data= {'msg':'no data'};
this.serviceData= data;
this.get= function(url){
$http.get(url).then(function (resp) {
data= resp.data;
});
}
}])
.factory('fac1', ['jsonService', function(jsonService){
jsonService.get('json/data1.json');
return jsonService.serviceData;
}])
.factory('fac2', ['jsonService', function(jsonService){
jsonService.get('json/data2.json');
return jsonService;
}])
When I use the factories in a controller like:
myController.f1= fac1;
myController.f2= fac2.serviceData;
I can see that fac1 and fac2 both return the same object, they both have {msg:'no data'}, if I change one then they both change.
My question is:
Even though I can break on the service and see data= {msg:'no data'} and see it being set to the response data - why do I not see any change in fac1 or fac2 ?
All I can think is that somewhere there must be more than one var data, something is not a 'singleton' ????
EDIT: I have now tried:
this.serviceData= function(){return data;};
and:
myController.f2= fac2.serviceData(); // this is always the 'no data' object
myController.f3= fac2.serviceData;
if I then (a long time later) call:
var something= myController.f3();
then I do get the json data... but myController.f2 is still {msg:'no data'} why ?
Ok, after trying m.e.conroy's suggestion I finally figured it out...
The problem is nothing to do with angular, it's how javascript passes objects.
(see: Is JavaScript a pass-by-reference or pass-by-value language? )
The factories passed back a 'copy-reference' of the original {msg:'no data'} object, and when the service eventually assigned:
data= resp.data;
that replaced 'data', but the factory-supplied references persist as the old object.
Now, if I do:
.service('jsonService', ['$http', function ($http) {
var data= {'msg':'no data', 'result':null};
this.serviceData= data;
this.get= function(url){
$http.get(url).then(function (resp) {
data.result= resp.data; // update properties of the data object
data.msg='got data!'; // instead of replacing it
});
}
}])
...then everything makes sense!
The variables in myController are changed when data arrives (since I have not 'swapped out' the data object).
Obviously, I still have the problem that my two factories return the same object (I'll look at Sacho's suggestion on this) - but I think I've learned something pretty fundamental here.
Try this:
this.serviceData = function(){
return data;
};
Also you probably have a race situation. $http may not have returned by the time the application asks for the serviceData
The difference between angular's "services" and "factories" is miniscule - I suggest just using one or the other, and sticking with it. From this point out, I'll refer to these elements as "services", even though I exclusively use angular.factory to declare them.
For what you ultimately want to do, there is a much simpler solution - simply return the promise from your service.
this.get= function(url){
return $http.get(url)
}
Then in your controller/directive/whatever, just use it like:
jsonService.get(url).then(function success(response) {
// do things with the response
})
But you seem to want to use a service to create many instances, so here's a contrived example achieving that:
.factory('jsonService', jsonService)
jsonService.$inject = ['$http']
function jsonService($http) {
return Fixed
function Fixed(url) {
this.url = url
this.promise = null
this.get = get.bind(this)
function get() {
// This caches the request so you only do it once, for example
if (this.promise == null) {
this.promise = $http.get(url)
}
return this.promise
}
}
}
Then in your controller, you would do something like:
var fixedOne = new jsonService('fixedOne')
fixedOne.get().then(...)

Categories

Resources