Just about everyone these days uses Promises in one form or another. I use them enough that I created a VS Code snippet that produces this boilerplate:
Many times, you have some async function to call and want it to return a brand new promise on each call. However, there are some important use cases where you only need to execute the promise’s logic once per page load. Consider a user profile retrieval function. Most of the time, when users hit an app, you need to retrieve their user profile information from some backend data store (often via HTTP) to provide a personalized experience by accounting for their recorded preferences, show their name and that sort of thing.
Let’s assume for a moment that the user’s profile doesn’t change between page loads (I’ll come back this assumption shortly). This is pretty common in my experience. In this case, there’s no need to go out and retrieve the user’s profile each time a component on the page needs it to do its job. You can, of course, and many first-cut implementations do this. This will make your app unnecessarily “chatty” — multiple distinct components on the page, each finding the user’s profile in order to give that personalized touch.
You can cut down on that chatter by relying upon Promises’ built-in memoization (read about this important technique here if you aren’t familiar with the concept by Divyanshu Maithani). You can call the same promise multiple times. If it has already resolved()’d with a particular user profile record, subsequent calls resolve with the same user profile record without re-running its logic. In other words — fewer HTTP calls, less chatter.
This works best if you funnel all your http calls like this through a re-usable service type component such as an Angular service, a redux action or your favorite technique for implementing a data I/O layer. If your various UI components are making their own HTTP calls, then it’s more difficult to leverage this capability efficiently.
As a result of this, my expanded example now looks more like this:
If the getUserProfilePromise class property isn’t initialized, the getUserProfile method creates a new promise. If it has been initialized, it just returns the existing promise. In the end, the Promise’s logic (and expensive HTTP call) executes just once.
What if the assumption is wrong, though? What if the user’s profile usually, but not *always*, stays the same over the course of a single page load? This usually arises in my single page apps when a user edits their profile and that edit transaction doesn’t trigger a page reload. It’s easy to handle on the service— just null out the variable holding on to the promise. That will force the service code to re-execute the Promise’s logic next time it’s invoked.
I usually create a “reRead” type method just to make this clear in the code:
I’ve been using user profile as an example, but you can imagine there’s a class of data that only has to be read once per page load. In the app I’m currently working on, there are a handful of master tables that rarely change at all and if they do change while the user is on page, it’s OK if we wait on a page refresh before getting the latest. That includes, for example, a country master, a region master, menu options and things of that nature.
As always, I hope this is useful! Leave a comment with your thoughts and experiences!
</end>