AngularJS Tutorial: Solving Asynchronous Problems with Resolve

Codementor AngularJS expert and founder of the Angular UI organization, Dean Sofer, joined us during an AngularJS open office hours for an open Q&A session.

One of our viewers had an issue where changing bindings downstream would affect bindings upstream, and their dependencies were asynchronous. He had 3 cascading dropdowns, and whenever it was initialized, the bindings for the first one was set would get it, but the other 2 didn’t have data so they would reset those bound properties to null before they populated the first drop down. The viewer was looking into react for solving the issue, interested in Dean’s experience with such issues and how he dealt with such problems.

Dean’s response is as follows:

The text below is a summary done by the Codementor team and may vary from the original video and if you see any issues, please let us know!

You sound like you had my nightmare with UI Select2. I apologize beforehand to anyone who has used it because I wrote it and it was a mess. It had too many convoluted features and ended up with a lot of problems.

Anyhow, I can’t speak about react since I’ve never used it before, but I really like resolves.

A lot of the time in my applications, I had to deal with async logic where the page loads and you have a lot of null value and then you’re doing a bunch of AJAX requests to load in your initialization data. If you’re doing multiple ones at the same time, promises can help you chain things together and go from 20 asynchronous requests to 1 request, but you’ll still have to initialize a page of nulls and initialize the page with actual data a second later. Resolve turns most of your data logic into non-async, and it’s a godsend.

If you put as much possible into your resolves, you’ll be thanking yourselves later.

A simple, stupid, possibly convoluted approach would be creating nested states like 3 dropdowns where the 1st dropdown is state 1, and the 2nd one the sub-state and the 3rd one a 3rd state.

Just separate your defaults from your select data and make sure you don’t have reference issues. Make sure your defaults are somewhere else that’s preserved and pristine and intact and you load in the results. That’s what I had to do with my UI select—I had to keep checking my defaults every time. In UI select 2 there were like, 4 different asynchronous events. A nightmare. If you’re interested in a less bloated version of UI select, you can take a look at the AngularJS-native version at GitHub.

How do you inject with resolve?

When you’re using resolves, they should all be functions so they could be executed. So if your code is like

I’m guessing you’ll get an error where this gghc.drill.state.wait_for_loaded_manager_list doesn’t exist when this line of code is being executed, because you got to remember it is going to be executed during the config phase, not during the “this route is being loaded” phase. The value of s is being set while the whole thing is being parsed, whereas the value of r is set to a function and we can call that function way later when the route is actually being spun up vs the second version which is happening when we’re storing the routes.

You could just have the function return that same exact value, it doesn’t have to return a promise. I have a resolve which is just a function and it returns true or null, because I had static data and didn’t want to asynchronously load a data or it was already available for some reason. But wrap it in a function.