An in-depth guide about working with Interdependent Promises
As a developer, I'm constantly looking for ways to write cleaner code.
In this article I won't explain the basics of Promises, but if you're looking for that, check out Dave Atchley’s article, he does a great job at it.
Disclaimer: Looking for async/await examples? Jump to the end and click on the repository link.
Although Promises are not an exclusivity of HTTP requests, that's what they're usually used for, so this will be the topic of this article's examples.
Let's get started:
This is a straight-forward piece of code and does its job well. However, if we take the same function and add more functionalities, such as caching, it can start getting complex. Here's an example:
As you can see, this example is not as clean as the previous one.
fetchAndCacheUser does way too many things. Sure it's not the end of the world, but ideally each function should do just one thing, so it's easier to test and reuse it.
This problem becomes even more apparent if we add another level of caching. So let's add Promise caching (to prevent two identical requests to be made) and see how it looks:
We're even farther away from "doing just one thing". The more things we add to this code the messier it will get, as well as harder to reuse. If we decide to create a
fetchAndCacheItem for example, it would require us to copy all this code.
Breaking it down
The first step for breaking this down is to separate things into more functions, each one taking care of one concern. What we're gonna do is create three functions, each one responsible for doing one of the three things:
- Cache promise
- Cache result
- Fetch data
The main challenge here this to connect one piece to another, since not all of then need to execute every time (e.g. when cached). To accomplish that we’ll provide callbacks to the cache functions, so they be called when the cache is not present.
Here's the code: (caching methods are hidden for clarity)
Much better huh? We do have more lines of code, but it's a lot easier to read an maintain. Going back to the
fetchAndCacheItem mention, with our concerns separate, we can start to see a path for reusing the same functions.
The next step
We've already come to a satisfactory point, but what if I tell you we can do even better?
Taking a look at our last function,
fetchAndCacheUser, we can see that the functions are declared in a reverse order of execution, which can be quite confusing. We also have to declare a new variable and assign it a function for each step, cluttering the code.
To solve these problems, I created the
promise-cascade library. Here's how the
fetchAndCacheUser` function looks like with
As you can see, the code is now written in the natural order and doesn't have the
const ... = () => ... clutter.
In some cases that make massive use of these functionalities, it can be helpful to extend
PromiseCascade and create helper methods, so instead of
cascade.push(something.bind(this), value1, value2), you can call
cascade.something(value1, value2). You can see examples of this on the GitHub repo.
For more details and examples (including
async), check it out on GitHub. If you like it, I appreciate you giving it a 🌟 star.
❤️ Like. Share. Leave your comment.
Don’t forget to spread the love. Throw in your like, share with your friends and colleagues. You're also very welcome to leave your comment below.
You can stay tuned for things I create on twitter.com/pedsmoreira or signing up to my newsletter: