Angular’s $q.defer and $q.all are cool. I promise.
So, what’s the fuzz about promises and what’s the “angular’s way” of doing them?
Let’s make a $35 billion company
Let’s say we are building Twitter, (and to keep things simple) we’ll have two collections on your database: users and tweets. Each user has a list of tweet ids associated with that user.
Once a user logs in, we’ll have 2 api requests to make: 1- get the users, 2- get the tweets associated with the user. Once I get the users and the tweets, we want to run a for loop to connect each tweet with its appropriate user.
Ok. So… how will we know when we get the data back (our users data and our tweets data)? It could take 2 or 8 hundred mini-milliseconds! By then all of your code would have run and all of your page rendered.
How do we fix this?
We use promises. Promises allows us to “put a hook” on the api request, and change its status when we get the data back. Once the status changes, a function will be invoked.
$q.defer is the vehicle that Angular uses to make that happen.
So now we can invoke a function when we hear back from Twitter’s api, but how would we know when we hear back from both of the functions. Remember we only want to connect each tweet with the user, once we have both the user and the tweets.
$q.all allows us to trigger a response once all of our api requests and responses have been completed.
Again, we use $q.defer to trigger a response when we hear back from an api request, and we use $q.all (combined with $q.defer) to trigger a response function when we hear back from all of our api requests.
I will have a controller that will rely on my getData service to get the data from the api. Whenever I get the data from the api, I’ll give the data back to the controller. and then, display the data on my page.
Wtfetch just happened?
We defined all of our promises. In this case, we named them one, and two.
Once our first requests comes back successfully we resolve one and pass the response. If there was an error associated with it, we reject it ☹
Now we need to wait for the second request to come back (or maybe it came back first!). If it was successful, we resolve it. If it wasn’t we reject it.
Once both of your promises are resolved, the all variable triggers its response on the controller’s end. We use a .then to catch that. There, we receive as many arguments as we resolved $q.defer() on our service. In this case we get two arguments, one with our user data and the other one with our tweets data.
We can now connect each tweet with its respective user. Voila! You read the whole blog post… I can’t believe it.
If you forget what methods are built into $q.defer(), try console-logging-it. You’ll see something like this:
This should remind you, that you can invoke notify, reject, or resolve (don’t worry too much about notify), and you should return your promise.
As a last note, I feel obligated to refer you to Angular’s docs (although they suck): https://docs.angularjs.org/api/ng/service/$q