I'm having trouble figuring out the success and error callbacks inside $http in angular and the "then" part of a promise. The $http service returns a promise. Is the "success" callback an example of a "then"? What if I stick $http inside my own service? How would I do this?
I think code is easier to show my questions:
app.controller('MainCtrl', function ($scope, $log, BooksService) {
BooksService.retrieveAllBooks().then(function(results) {
$scope.allBooks = results;
});
});
app.factory('BooksService', function($http,$log) {
var service = {
retrieveAllBooks: function() {
return $http({
method: 'GET','https://hugebookstore.org/allbooks'
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
}
}).success(function(data, status, headers, config) {
var allbooks = transformDataIntoBooksArray(data);//this function exists and just takes raw data and turns them into Book objects
return allbooks;/*how is this "success" callback related to the "then"() callback in app.controller above?*/
};
}).error(function(data, status, headers, config) {
$log.error('here is an error'+data + status + headers + config);
});
}
};
return service;
});
Questions about the app.controller
code:
do I need to use a "then()"
function inside app.controller?
I just want my controller to fetch me a list of all the books using the BooksService
. The BooksService
already has a "then
" type of clause, which is the "success
" callback. It seems like I have an unnecssary "then
". Is that true?
Also, when is the "then
" called, and can I put anything in the then's
callback function's parameters?
I don't understand what parameters are supplied by default and what I can add.
Questions about the app.factory
code:
First, this is what I understand the code to be doing.
I'm creating a BooksService
using the factory() methods and not the service() methods available in Angular.
I'm defining a function called retrieveAllBooks()
that under the hood, is making an asynchronous GET request using $http in Angular, which itself is a service. RetrieveAllBooks()
is a nothing more than a wrapper around the $http GET service, which makes it easy for clients to simply call BooksService.retrieveAllBooks()
and be handed an array of Book objects.
When is the "success
" callback executed and what is its relation to the "then
" callback in my app.controller?
It doesn't appear that a return
value inside my success
() callback is ever returned back to app.controller
. Why?
How can I get the allbooks array returned back to the app.controller which is what originally called BooksService.retrieveAllBooks()
?
Are there any other parameters allowed in the success
callback?
What do I need to return from the retrieveAllBooks
() function definition? Do I return the $http promise
alone, or do I need to return
something from both the success and error
callbacks as well?
I know this is longwinded but I hope that someone can help me, b/c this to pattern--separating out my network calls into its own service
layer as opposed to calling $http
directly inside my controller
layer, will be done over and over again.
Thanks!!
The
success
anderror
handlers are specific to the promise returned by$http
. However, they're similar to.then(function onFulfill(){}, function onReject(){})
.It's up to you if you want to return that promise directly or implement something else.
Generally, your controller shouldn't be concerned about how your service handled the request. Thus, in my opinion, you shouldn't return that promise directly. Just handle the success and error case in your service. Return the result if the request succeeds and throw an Error if the request fails.
You can then use the generic
.then(function onFulfill(){}, function onReject(){})
pattern in your controller, as this is always valid and expected with promises in Angular.The
onFulfill
callback always receives your result as a parameter, theonReject
callback receives the Error as a parameter.So, what options do you have? Either drop your
.success
and.error
callbacks in your service altogether and handle the transformation in the success case in your controller, or create a new deferred promise to return the transformed results:Although, we can save that if we consider: - Errors are tracked by Angular already - The deferred is excess, and can be avoided - Content-Type and Accept are generated by Angular and the serer anyway. - We can save the anonymous wrapper for our action
So, we end up with: