While using AngularJS's $http service I've found hard to manage all urls to backend - they're spread around controller's code. Sometimes they're even duplicated. Mostly all of them are in form of $http.get('/api/something').then(...).
To put all of them into different services sounds quite unreasonable: it is just one line of code with may be just small modifications (like adding header etc).
Other solution could be putting them into constants, but in this case I would still use $http.get(APIURLs.SomeURL) that looks like little bit verbose...
So the question is: what is the best way to manage URLs to back-end?
Currently I came up with idea of grouping them into servicies and expose them as calls to $http. Here is my solution: http://plnkr.co/edit/VjqXHBV54bmjKCuGJ4qX?p=preview
Service:
.factory('AdminAPI', function($http) {
var apiMap = {
'DeleteAuth': {url:'/api/oauth/delete',method:'PUT'},
'GetInvalidUser': {url:'/api/users/invalid',method:'GET'},
'CreateItem': {url:'/api/items/create',method:'POST'}
};
var api = {};
var prepareCall = function(config) {
return function(params) {
var requestConfig = angular.copy(config);
if (config.method=='GET')
requestConfig.params = params;
else
requestConfig.data = params;
return $http(requestConfig);
};
};
for(var name in apiMap)
api[name] = prepareCall(apiMap[name]);
return api;
});
And in controllers I do something like:
AdminAPI.DeleteAuth({data:123}).then(function(result) {
//
});
In this case I have some abstraction (do not have to inject $http into controller), so unit-tests become little bit easier (I do not have to use $httpBackend service, just mock my service calls).
Make use of angular Module.constant:
Define angular module wrapping this object:
angular.module('myApp.constants', []).constant('config', {
ROUTES: {
home: '/home.html',
about: '/about.html'
}
});
load myApp.constants module into application with all the others:
angular.module('myApp', [
'myApp.constants',
'myApp.services',
'myApp.controllers',
'myApp.filters',
'myApp.directives'
]);
After that you can inject config dependency and access defined hash.
Good question. My suggested approach is to put the constants in a constantdeclaration like this:
angular.module('fooApp').constant('config', {
api: {
baseUrl: 'http://api.example.com/api',
key: 'SECRET_API_KEY',
}
});
And you could implement a httpResourceFactory that is responsible for creating $http or $resource references that points to different endpoints using the constants defined in config.
This could be implemented in a service.
Then all API endpoint definitions can be put into a single service.
angular.module('fooApp').factory('dataService', ['httpResourceFactory', function(httpResourceFactory) {
var PUBLIC_API = {};
PUBLIC_API.Orders = httpResourceFactory('/orders/:id');
PUBLIC_API.Users = httpResourceFactory('/some-url/users/:id');
return PUBLIC_API;
}]);
Then in your controller you may inject dataService and do stuff like this:
$scope.users = dataService.Users.query();
Hope this clarified it. I'm in a hurry, so ask more concrete and I will provide more examples later on.