I have some web services that I want to call. $resource or $http, which one should I use?
$resource: https://docs.angularjs.org/api/ngResource/service/$resource
$http: https://docs.angularjs.org/api/ng/service/$http
After I read the two above API pages I am lost.
Could you please explain to me in plain English what is the difference and in what situation should I use them? How do I structure these calls and read the results into js objects correctly?
I feel that other answers, while correct, don't quite explain the root of the question: REST is a subset of HTTP. This means everything that can be done via REST can be done via HTTP but not everything that can be done via HTTP can be done via REST. That is why $resource uses $http internally.
So, when to use each other?
If all you need is REST, that is, you are trying to access a RESTful webservice, $resource is going to make it super easy to interact with that webservice.
If instead, you're trying to access ANYTHING that is not a RESTful webservice, you're going to have to go with $http. Keep in mind, you could also access a RESTful webservice via $http, it will just be much more cumbersome than with $resource. This is the way most people have been doing it outside AngularJS, by using jQuery.ajax (equivalent of Angular's $http).
$http is for general purpose AJAX. In most cases this is what you'll be using. With $http you're going to be making GET, POST, DELETE type calls manually and processing the objects they return on your own.
$resource wraps $http for use in RESTful web API scenarios.
Speaking VERY generally: A RESTful web service will be a service with one endpoint for a data type that does different things with that data type based on HTTP methods like GET, POST, PUT, DELETE, etc. So with a $resource, you can call a GET to get the resource as a JavaScript object, then alter it and send it back with a POST, or even delete it with DELETE.
... if that makes sense.
$http makes general purpose AJAX call, in which general means it can include RESTful api plus Non-RESTful api.
and $resource is specialized for that RESTful part.
Restful Api came to prevalent in recent years because the url is better organized instead of random url made up by programmers.
If I use a RESTful API to construct the url, it would be something like /api/cars/:carId.
$resource way to fetch data
angular.module('myApp', ['ngResource'])
// Service
.factory('FooService', ['$resource', function($resource) {
return $resource('/api/cars/:carId')
}]);
// Controller
.controller('MainController', ['FooService', function(FooService){
var self = this;
self.cars = FooService.query();
self.myCar = FooService.get('123');
}]);
This will give you an resource object, which is accompanied with get, save, query, remove, delete methods automatically.
$http way to fetch data
angular.module('myApp', [])
// Service
.factory('FooService', ['$http', function($http){
return {
query: function(){
return $http.get('/api/cars');
},
get: function(){
return $http.get('/api/cars/123');
}
// etc...
}
See how we need to define each common operation on RESTFul API. Also one difference is that $http returns promise while $resource returns an object. There are also third-party plugins to help Angular deal with RESTFul API like restangular
If the API is something like /api/getcarsinfo. All left for us is to use $http.
I think the answer depends more on who you are at the time you're writing the code. Use $http if you're new to Angular, until you know why you need $resource. Until you have concrete experience of how $http is holding you back, and you understand the implications of using $resource in your code, stick with $http.
This was my experience: I started my first Angular project, I needed to make HTTP requests to a RESTful interface, so I did the same research you're doing now. Based on the discussion I read in SO questions like this one, I chose to go with $resource. This was a mistake I wish I could undo. Here's why:
$http examples are plentiful, helpful, and generally just what you need. Clear $resource examples are scarce, and (in my experience) rarely everything you need. For the Angular newbie, you won't realize the implications of your choice until later, when you're stuck puzzling over the documentation and angry that you can't find helpful $resource examples to help you out.
$http is probably a 1-to-1 mental map to what you're looking for. You don't have to learn a new concept to understand what you get with $http. $resource brings along a lot of nuance that you don't have a mental map for yet.
Oops, did I say you don't have to learn a new concept? As an Angular newbie you do have to learn about promises. $http returns a promise and is .thenable, so it fits right in with the new things you're learning about Angular and promises. $resource, which doesn't return a promise directly, complicates your tentative grasp on Angular fundamentals.
$resource is powerful because it condenses the code for RESTful CRUD calls and the transformations for input and output. That's great if you're sick of repeatedly writing code to process the results of $http yourself. To anyone else, $resource adds a cryptic layer of syntax and parameter passing that is confusing.
I wish I knew me 3 months ago, and I'd be emphatically telling myself: "Stick with $http kid. It's just fine."
I Think it is important to emphasize that $resource expects object or array as response from server, not raw string. So if you have raw string (or anything except object and array) as a response, you have to use $http
When it comes to choose between $http or $resource technically speaking there is no right or wrong answer in essence both will do the same.
The purpose of $resource is to allow you to pass in a template string (a string that contains placeholders) along with the parameters values. $resource will replace the placeholders from the template string with the parameter values those being passed as an object. This is mostly useful when interacting with RESTFul datasource as they use similar principles to define the URLs.
What $http does is to perform the Asynchronous HTTP Requests.
resource service is just useful service for working with REST APSIs.
when you use it you don't write your CRUD methods (create,read,update and delete)
As far as I see it, resource service is just a shortcut,
you can do anything with http service.
One thing i noticed when using $resource over $http is
if you are using Web API in .net
$resource is tied up into one controller that execute a single purpose.
$resource('/user/:userId', {userId:'#id'});
[HttpGet]
public bool Get(int id)
{
return "value"
}
public void Post([FromBody]string value)
{
}
public void Put(int id, [FromBody]string value)
{
}
public void Delete(int id)
{
}
While $http could be of anything. just specify the url.
$http.get - "api/authenticate"
[HttpGet]
public bool Authenticate(string email, string password)
{
return _authenticationService.LogIn(email, password, false);
}
it's just my opinion.
The $resource service currently does not support promises and therefore has a distinctly different interface to the $http service.
What I could understand is that if you are having a RESTFUL resources to manage, using $resource will let you define the resource once in code, and use the resource for multiple operations on the resource. This increases the readability and maintainability of the code.
If you just want to have general purpose calls not managing it like post, delete, update, you may go with $http or $resource (as you prefer).
Related
i been reading about services or factories in angularjs, but im having some trouble finding the best solution, basically i need to pass some data from one controller to another controller, it is a boolean value, but i dont want to create a service for just a small task.
I believe that wouldnt make much sense for just a small job. is there other way in angularjs for this type of situations? Where i could pass small data between controllers. I been looking around in angularjs documentation, but cant figure out the best solution.
Use $rootScope.emit()
in Controller A
$rootScope.emit('toggle',true);
in Controller B
$rootScope.on('toggle', function(value){
})
For tiny items, you could use parameters. The the end user, they'd look like a part of the URL string. This is avaible with and without using ngRoute. Have a look at this stack question.
For more complex data or data that's unsuitable to displaying to an end user, use a service or factory. Seems like overkill, but it gives you greater flexibility.
A $broadcast/$on pattern just gets messy and harder to troubleshoot.
If it's parent/children controller, you can transfer your value with $scope or $emit/$broadcast.
If controllers are on the same level(siblings) you can make wrapper controller for them to store shared data.
If you think there would be similar requirements for other tasks you can consider service, and making it abstract and reusable(some sort of helper).
In any way, you didn't provide enough of info, and there could be a lot of solutions until we see real example.
If your controllers have a child parent relationship (in any level) then you can try with $broadcast or $emmit to throw the data and $on to catch that with a a event. Otherwise inject $rootScope to one of them and trigger either $broadCast on the monitor of $rootScope, or $emmit on the monitor of $scope and catch thet data using $on('eventName', function(ev, data){}) correspondingly.
I have a repeated set of API calls in an Angular controller.
The relevant data is of course the API URI, POST or GET, some header data, and JSON objects. The API call always returns a JSON object.
I started to use a Directive but that seems most relevant for data that is used with $scope (e. g. in the View). This data runs under the radar and might eventually generate data used in the view but most usually not and most usually not in a way that can be abstracted.
So: Does this mean I shouldn't use a directive? If I don't use a directive, would it be better to use a JS Object (seems more modular) or Function (seems more variable friendly) to handle this code?
Yes, I get that objects can contain functions, but functions can also contain callbacks so...looking for kind of a "best practices" here. In terms of modularity and flexibility.
You should create Angular service for that.
https://docs.angularjs.org/guide/services
Your service will contain a method, lets say "getResults" which will make an API call and return either data or a promise ($http). Then you can inject you service to your controller and use that method to get the data and assign it to $scope.
An Angular service is certainly preferred to a more general JavaScript one because it allows you to take greater advantage of Angular's scope and other such things. Between Angular's Factory, Service, and Providers, a Service is the most in line with what you're trying to do since a Factory is too basic and generally used to solve smaller problems while a Provider is used -- as it says in the Angular docs -- "only when you want to expose an API for application-wide configuration that must be made before the application starts." Which is not what you're trying to do.
I would like to be able to capture all HTTP requests and responses, and modify them, before they get to the rest of an EmberJs app. I would like to do this globally - across the entire app. I have not been able to find this digging through the API. How can this be done?
(Modification is to perform some conditional logic based in certain headers, or to add or modify certain headers).
In AngularJS, you can accomplish this using something like this:
App.factory('AppHttpInterceptor', function($q) {
return {
request: function(req) {
//modify request
return req;
},
response: function(res) {
// modify response
return res || $q.when(res);
}
};
});
App.config(function ($httpProvider) {
$httpProvider.interceptors.push('AppHttpInterceptor');
});
First, it's important to note that Angular and Ember are not built to serve the same purpose. They are both javascript frameworks, and that's about where the similarities end. Another big factor in the difference of async requests in the two framework is Angular's integration of promises into it's async services. Ember async services are not promise based, and therefore response interceptors are not possible (see my note below).
AngularJS provides $httpProvider as a configurable singleton that returns a configured instance of $http as a promise object. Angular focuses on services rather than methods (although it does have a few methods it gives you), and that's what sets Angular apart from other frameworks like Ember, which give you a structure to build services, but doesn't provide services in it's core.
Instead, with Ember, you'd have to build a service and service provider concept yourself. You could take something like cerebris/ember-rest, and extend it in such a way as to use properties you describe. This library provides an Ember.resource method, which you could use prototype to extend from there:
Ember.ResourceAdapter.extend({
_prepareResourceRequest: function(params) {
params.beforeSend = function (xhr, settings) {
//set your xhr interceptors here
}
}
});
Edit: Clarification on use of $ajax in ember and $http in Angular (promises vs callbacks)
The biggest difference on how angular makes response interceptors possible, is that async requests in angular are promises, whereas $ajax calls are not. Without getting too much into the weeds, you can assign variables to each step of a promise, making it available for mutation/handling along every step of the way, whereas with $ajax, you can only perform operations when the data has completely returned. With Promises, assign variables to represent states at any point during the lifecycle of the promise, and using that reference, you can mutate the promise as needed, at any point in time prior to the event of the promise fully resolving.
Thus why it's possible to do request interceptors with $ajaxPrefilter but there is no good way to do response interceptors, using the abstract configuration approach with $ajax. To truly do in Ember what AngularJS does with $http, you need to create a promise based async request/response service, as opposed to utilizing non-promise based xhr requests such as $ajax.
jQuery does provide an $ajaxSetup() method, which you might be able to set a dataFilter property to and define a handler function, however this is not recommended. With angular, the $httpProvider can be configured by module, and through de-coupling and Separation of Concerns, this can become truly powerful, allowing you to encapsulate and cascade http interceptor configurations with a lot of control. Making the same changes to your ajax settings will register themselves on the global jquery namespace, and can cause conflicts if you need to grow your app.
One video I found particularly englightening on this subject was from ng-conf 2014: Christion Lilley: Going Postal with Angular Promises
Edit 2: addressing Ember.RSVP
While Ember.RSVP is indeed a promise class useable in the framework, it does not have any methods available to perform resource requests. This means you have to manually assign an http request instance to an instance of RSVP.deferred such that it resolves your http request before returning the promise.
This allows you to do interceptors on both sides of each individual request, but does not provide a solution for configuring interceptors for all requests. You'd have to create another function or service for that, and extend RSVP with this function.
I'm building an AngularJS app, and I would it to be respectful or the best practices.
Thus, when I have to call an external $resource or $http request, I do it in an external Service/Factory.
My problem is I don't know what is the best way for retrieving returned value of the Service into the calling Controller.
Currently, what I do is the following :
The controller calls the Service
The Service does the $http call and check the promise.
If promise is successful, the Service $broadcast an event with the returned object.
The Controller catches that event and does operations.
It works great and allows me to use the same event after different requests (ex: In a discussion, after retrieving all messages and after posted myself a message, the same event "new messages to display" is called)
.
But I finally decided to set up testing processes in my application (better late than never), and I realize that I could do it wrong.
--> When unit-testing my Controllers I want to mock some of my Services for returning given values. But as my Controller calls Services which doesn't returns anything (they fire events instead) I think it will be pretty hard and not natural to check Services "return" values. (I can always check if the Service has been called, but not the result).
.
Your opinion, have I done misconception errors ? I consider getting the promises directly into Controllers when calling Services, is this a good (better?) way to do it ?
I aware that each application have its own logic, but I think in AngularJS the number of "working" logics (that preserves modularity, and testability) are particularly restricted to some set of choices and best practices.
Any suggestion would be appreciated.
Without seeing your code, I have my ideas:
Your controller could receive that promise and do what it needs to do. There is no real need to broadcast anything. Your service call $http and then return the promise. When $http promise is resolved, your controller will know and can do what you need to do.
Testing functions in a service that doesn't return anything is not a problem, that is what spyOn is. You can check that the function has been called and that should be enough for your controller. You don't actually care what happens in the service, you cares about your controller (in the test controller, of course).
Please don't use events for such kind of interaction. They make a mess inside of the code and reduce maintainability. Sometimes you can use them but it is fine only for certain operations and for some specific situations. Using promises is good approach.
Here you have three different options:
Just return the $http promise object and handle it inside of your controller
Make your own promise with $q service and place inside of it your own logic for handling the response from $http or direct returning result (it is more flexible approach than the first one)
Just pass to the services a function callback which you can call there inside of your service to pass the result back to controller.
But you definitely don't need to use events in these cases.
What is related to unit-testing you will configure $httpBackend service to mock your queries and in this case everything will work fine and you can test anything you need ($httpBackend). It means that you can inject your service and it works fine (as instead of real http call it will return the object configured as a response in the $httpBackend). So you can still test your controller without need to make anything complicated to your services.
First of all I must admit I am quite new to Angular.js and I haven't used any new generation js framework like Backbone or Knockout before. I'm creating an application which communicates with server using RESTful API. I dug a lot into angular documentation and blog notes so as I could do it right.
I found examples mostly with $resource. It looks pretty good: many built-in methods, when you design your REST interface properly you don't even have to write anything more.
But I (and my whole team too) are more used to JavaEE way of thinking about model layer: lightweight model classes (POJO, etc), DAO classes persisting and fetching model and optionally service layer between DAO and controllers. On the other hand in Angular $resource creates something more resembling active record.
I've already come up with two ways how to implement DAO pattern in Angular:
Writing everything from scratch, going down to the $http abstraction level. I'd implement every DAO method as $http call, take care about errors.
Using $resource objects normally like lightweight model classes and passing them to DAOs which are the only unit responsible for calling actions like .$save() on them. Of course we cannot prevent calling it in different place, but solution with such convention is good enough for me.
Second way looks better for me because of reusing existing code. $resource has nice behaviour of promise object and I will be happy if I don't have to implement it myself.
So finally the main question: is active record approach is the only way of doing data access right in Angular, Backbone and other tools like that? Maybe somebody have already tried to incorporate similar solution more resembling DAO in his code and can share his thoughts about it?
And the second question: is $resource object sufficient when it comes to dealing with errors, connection losses and different problems? Is it worth to use $resource having this in mind or it's better to start with lower level $http.
I am at the beginning of the project and I know that this decision may well affect the whole project life later, so I want to choose the best.
I totally agree. Here is the way I do it:
bankApp.factory("CustomerRepository", function ($resource) {
var customerRepository = $resource("rest/customers/:id", {id:'#id'}, {'update': {method:'PUT'}});
// You can also add addition repository like $http calls onto the
// customerRepository like getting the count and other stuff.
return customerRepository;
});
Then you can inject the CustomerRepository where ever you need it. For example:
bankApp.controller("BankController", function ($scope, CustomerRepository) {
$scope.customers = CustomerRepository.query();
$scope.createCustomer = function () {
CustomerRepository.save($scope.customer, function (customer) {
...
});
};
...
$scope.saveCustomer = function () {
CustomerRepository.update($scope.customer, function (customer) {
...
});
};
});