AngularJS Architecture: Control your promises with $q

Lukas Ruebbelke
InstructorLukas Ruebbelke

Share this video with your friends

Send Tweet
Published 8 years ago
Updated 4 months ago

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.

[00:00] 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.

[00:28] 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?

[00:55] 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.

[01:19] 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?

[01:51] 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.

[02:15] 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.

[02:40] 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.

[03:06] 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.

[03:31] 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.

[03:51] 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.

[04:21] What this is going to do is loop over the categories and find the category with that name. Fairly simple.

[04:33] 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.

[05:02] 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.

[05:37] 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.

[06:01] This is the technique for manually creating a promise. We return it to the consumer and then we can either resolve or reject it.

[06:10] 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.

Weston Ross
Weston Ross
~ 6 years ago

Where do you draw the line between making a http request to store all your model data on the browser and making individual calls for each CRUD action ? I understand making the the call for the json files, "caching" the values and using lodash is for demonstration. But I also understand that angular and SPAs have an advantage that they make very few calls to the server. Is the method you have illustrated in this tutorial only for demonstration purposes only?