Learn how to manually control how asynchronous requests are handled with the use of promises. Because $http is built to work with promises, we saw a foreshadow of them in the previous lesson. We will take this a step further but seeing how to manually create a promise and then resolve or reject it as we see fit.
In the previous lesson, we learned how to make a remote server call using the http service that is part of the AngularJS core. The http service is built on top of promises. It implicitly returns a promise when you make a call to the server using the http service.
There are situations where you may want to actually do something before you actually pass that data back to the controller for consumption. For instance, what if you wanted to actually return a cached version of that data structure, not actually incur the overhead of making an extra call?
You would need a way to manually resolve that promise instead of allowing the http service to do that for you. The goal is to show you how to use promises in your model and do it in such a way that your controllers are oblivious to whether or not it was coming from the http service or you were manually resolving it.
This is where the q service comes in. AngularJS uses the q service to handle promises. We are going to inject the q service into the categories model. From here, let's go to where we're calling getCategories. Let's check to see if we actually have categories. Does it exist? Have we already made this call?
If it does exist, let's go ahead and just return a promise. We can use a method on the q service called when. What this does is it takes an object and it wraps a promise around it.
Now, what we're doing is we're saying, if categories exist, go ahead and return a promise using this when method. In the promise, put the categories. At this point, we are actually going to check to see if categories exist. If it does, then it will be as if we already made a call to the server and got categories.
This is a really gentle introduction into promises and probably the easiest scenario that you're going to see. But let's take this a little deeper. We are going to create a method called getCategoryByName. This is going to be a method that we're going to need in a future lesson. We'll go ahead and create it now.
We are going to create a deferred object by calling q.defer. This returns a deferred object. What I'm going to do here is create the bookmarks or the bookends for this. We actually create a deferred object and then we return the promise.
From here, we can manually resolve or reject the promise at our discretion. It's important to understand these two parts, is that you create a deferred object by calling q.defer. Then, you return the promise object on that deferred object.
From here, let's go ahead and fill this in. I'm going to create a convenience method here called findCategory. What this is going to do is just loop over the categories collection and compare the name of the current category to the categoryName parameter that we actually need to define up here. There we go.
What this is going to do is loop over the categories and find the category with that name. Fairly simple.
From here, we will say, does categories exist? If so, then we are going to resolve the promise with the results of findCategory. The reason why we're checking if categories exist is because you could possibly want to find a category before you've actually had the opportunity to go and fetch the categories from the server.
If categories does not exist, then we need to call getCategories. From there, take the result and we will use the result to resolve the promise like so. We are simply just adding in an extra step.
If categories exist, we're just looping over the categories and finding the category for that name and resolving the promise with that value. If it does not exist, we are making a call to the server, getting the categories, and then resolving the promise that we created with the results of findCategory. We're just inserting that extra step.
This is the technique for manually creating a promise. We return it to the consumer and then we can either resolve or reject it.
Stay tuned for the next lesson where we will continue to refactor the functionality from the main controller back into the appropriate parts of the eggly application. I look forward to seeing you in the next lesson.