Now let's learn how use the $http service to make requests to remote servers. In our case, we will load the data from JSON files and then make them available in our controllers. We will see a few techniques that I frequently use to make working with $http data a lot more convenient.
What would the bookmarks-model look like if the bookmarks where a nested resource on the api server? Like when you'd get to a bookmark using a URL like: '/api/categories/design/bookmarks'
The URLS.FETCH property would then depend on the currently viewed category. Would it be something like this?:
model.getBookmarks = function(categoryName) {
return $http.get('/api/categories/' + categoryName + '/bookmarks').then(cacheBookmarks);
};
Rogier, that is correct and why I love REST so much because you simply have to construct the proper endpoint. I would extract the logic behind generating the URL into a separate method but you are headed in the right direction.
Out of curiosity, why did you capitalize the URLS object?
Good question. That is just a convention I use to imply it is a constant as endpoints generally do not change over the lifecycle of an application.
I see. Many thanks. One more quick question. Why use $http.get(URLS.FETCH).then(...), instead of $http.get(URLS.FETCH).success(...)
Doesn't using .success save a few steps, as it returns the data directly and not the promise object? So no need for the extract and cache functions? Super confused here, ha.
Because we are dealing with an asynchronous operation, we definitely want to return a promise. This allows use to ensure uniformity in how we handle the response even though we are not sure when it will complete.
By returning a promise, we can also control what and how we respond to the controller that is requesting the operation i.e. caching, etc.
Hey Lucas, thanks for entertaining my ignorance! Need to read up and get smarter on (i) how promises work and (ii) caching. Still quite confused.
Re caching, can you recommend any reading on how caching works / when to use it / how to use it in JS? I get the broad idea ('load something once instead of multiple times') but the implementation is a black box to me.
Re promises, strange that the angular documentation only covers using $http with .success and .error.
So I'm trying to get my JSON data to load to the template and I did everything in this video. However, when I console.log(result)
inside of the getCategories()
function in categories.js, the result ends up being my entire index.html template??? Very bizarre and I'm not sure why it is reading the HTML rather than my json file. Help please!
Hi Matt -- are you using an HTTP server to serve up the web application? What endpoint are you hitting in your categories service? Can you trace it out in the network tab in the Chrome developer console?
I'm tracing through my steps, console.logging everything...so this is what I've found.
On the extract(result)
function, when I console.log(result)
, I can see that inside of the data property is my entire index.html for some reason, when it should be the array of objects from my JSON file. As excepted, logging result.data
returns the index.html file.
I'm building my project out with the MEAN stack, so I am using an Express.js server. My endpoint is similar to what you have in the video:
URLS = {FETCH: '/data/categories.json'}
I added the '/' in the beginning to try and route it through the main directory. When I trace it through the network tab, I see that the Request URL is as follow:
Request URL:http://127.0.0.1:8080/data/categories.json
So just to clarify... you are hitting this URI http://127.0.0.1:8080/data/categories.json
and getting the contents of index.html
? If so, I am pretty certain that there is a problem with your Express middleware.
Yea that's seems to be what is happening. Do you have any ideas as to what to look for?
You need to set up an Express route that is specific for http://127.0.0.1:8080/data/categories.json
and return the categories.json
file. You could even skip the JSON and just return the collection from within your Express app.
why we are adding this extra method
function cacheBookmarks(result) {
bookmarks = extract(result);
return bookmarks;
}
isn't doing this is enough ?
model.getBookmarks = function() {
return $http.get(URLS.FETCH).then(extract);
};
any reason to pipe that data to cacheBookmarks
?
Hi Jayendra -- I added that in to show how to implement caching as well as making your service stateful. There are cases where you may not want to store your results in the service and fetch a fresh copy every time but for performance reasons, it would make sense to not have to fetch a fresh copy every time. Especially if the data is fairly static.