AngularJS $q

The use of promises, why we need them.

Firstly, we use promises to avoid nesting requests inside other requests callback functions. Requests are often nested so we do not return data before all calls have been made.

Taking an example of a file sharing service, where there are users, and each user has a list of files. This would mean that we would fetch data for a user. Once this was complete we would fetch the data for their list of public files once the profile request is complete.

Why is this a bad idea? Well, since fetching a files list is not dependent on any of the data relating to the user. We should be making the requests in parallel. We only nested it before to ensure that the profile data didn't resolve and return before the files data returned.

Enter $q.all()

With $q.all(), we can pass in an array of deferred promises. This will make $q wait until all the promises have resolved. Since we are passing in an array, we can conditionally push promises onto the array, if and only if we need to wait for that promise to resolve.

For example, if we do not need to fetch files (maybe the current user doesn't have permissions to), we
simply do not push the promise onto the 'promises' array. Thus, $q.all() will not know of it and will never try to resolve it.

Process

We declare a $q.defer() for each set of data we may need to wait for. And we create a promises array onto which we will add promises when needed. We then conditionally add the promises to the array.

We pass the promises array into $q.all() which results in the then() function having an array of all the responses. If this is done in a resolve function of an AngularJS app, we can resolve the data to make it accessible to the route controller.

Note

This should see a small performance boost since we are now fetching files and profile data simultaneously rather than semi-synchronously.

Stephen Pitchford

Frontend web developer. Lover of AngularJS and all things web.

Subscribe!