The ability to reply to discussions is limited to PRO members. Want to join in the discussion? Click here to subscribe now.

AngularJS Architecture: Control your promises with $q

AngularJS Architecture: Control your promises with $q

6:26
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.
Watch this lesson now
Avatar
egghead.io

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.

Avatar
Reinder

It seems that depending on the timing of the getCategoryByName and the getCategories call, additional getCategories HTTP requests can be triggered as there is a (n obvious) delay between calling getcategories and setting the categories in the caching functions after receiving the result. If getcategoriesbyname is triggered in between these events, (categories) will be false and therefore an additional call will be triggered.

What is the best-practice way to resolve this type of situations in angular to avoid multiple triggers? Maybe setting a loading variable and put a watch on this variable so the getcategory by name function can be resolved after the getcategory call is resolved in the promise?

Very good series to get started in Angular!

In reply to egghead.io
Avatar
Lukas

Hi Reinder --
Generally this is a non-issue and depending on the payload, I may even just let it happen as it has no real effect on the behavior of the application. With that said, I have used a flag to essentially bounce additional calls until the original call finishes. So what you said. :D

In reply to Reinder
Avatar
Reinder

Thanks, I understand it is not an issue in this app, i'm using the tutorial to learn angular and build a similar but different app in parallel, there I do have this issue sometimes.

This could also be an issue in my understanding of the databinding and I should copy the full bookmark list instead of returning a sub-array (new object) from the model to trigger this correctly.

In my app I'm using two views on the same data array to display the data (lets say bookmarks and favourite bookmarks) where the bookmarks should be loaded once and the controllers of the views get the right bookmarks based on filtering the list. In this case depending on the timing of the calls the bookmarks can be loaded twice. If the view is refreshed and the array re-loaded the bookmarks do show up.

In reply to Lukas
Avatar
Rick

Hi Reinder,

I ran across this very situation. The equivalent of the getCategories() I had was quite expensive on the server side, so having it go out and do that call multiple times was getting a little too lengthy for me.

What I ended up doing, and keep in mind that I'm still learning this as well, was as follows:

I added a var categoriesPromise along side the categories and model variables, and then in the model.getCategories function, I changed it to

return (categories) ? $q.when(categories) : (categoriesPromise || categoriesPromise = $http.fetch(URLS.FETCH).then(cacheCategories);

In this way, I hold on to the original $http() promise and return that rather than generating a second one. So, both the promise and the result are cached. Seems to work. Again, I'm still new to angularJS and $q, but so far, this seems to working (I could be missing something obvious tho!)

Hope this helps rather than harms. :)

In reply to Reinder
Avatar
Reinder

Hi Rick, thanks for sharing your solution. The solution I have implemented is by setting a loading flag on loading and a watcher that is removed after the update to retrieve the content.

I haven't checked your solution in mine but I sometimes need to reload the full list from the backend for which i use the same function, when keeping the promise as variable this might result in the original promise.

If it works, it works :)

In reply to Rick
Avatar
Weston Ross

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?

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?