We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.

alferguson • 4 years ago

Hi Jon, great article. I am confused what the exclamation point does in your 2nd snippet of code.

return userPromisesCache.get(userId)!;

Is this a new feature to JS? If so, can you attach some documentation to it? Thanks.

Jon Mellman • 4 years ago

Jan is correct, this is TypeScript's non-null assertion operator. Sorry for the confusion!

Jan Jablonski • 4 years ago

These code snippets are written in TypeScript and the exclamation mark informs the TS compiler that the result of the userPromisesCache.get(userId) is not undefined (or null).

xgqfrms_ms • 4 years ago

awesome solution

Khaled Mohammad • 4 years ago

Hi Jon, great article!
I was thinking about one thing, if say we are caching http responses like this, and our web app is running for a long time (lets say a week or so), and between that it is likely the data will change, what strategy you would take to invalidate the cache of the memozied function? I was thinking of expiring it after a specified time (1 day or so).

Jon Mellman • 4 years ago

Yep, giving each cache entry a TTL is usually a reasonable caching policy. memoizee (and other libraries like lru-cache) will give you this functionality out of the box, which is nice.

Something I should have noted in the post is that, if you're writing an API client for the browser, you should probably look into browser-native HTTP caching before reaching for a code solution like this memoization pattern.

The exact cache policy you employ will usually need to be tailored to your specific requirements around freshness, latency, and memory usage.

Gregory Jacobs • 4 years ago

Hey Jon. Nice article! You should also build error handling into the example because if the promise rejects, all subsequent calls to getUserById() with the same args are going to receive a rejected promise! Would probably want them to retry the network call in this case.

This detail might invalidate the out-of-the-box memoization solution, but maybe an example of a thin memoization helper for promises could be created as well.

Best,
Greg

Jon Mellman • 4 years ago

Thanks Greg, you're absolutely right! I'll post an update as soon as I'm able.

I think memoizee's promise mode is a good out-of-the-box way to get error handling. It will eject rejected promises from the cache, allowing the client to retry.

Baptiste LE MORLEC • 4 years ago

The last snippet could be written like so ?

import _ from 'lodash';
const getUserById = _.memoize((userId: string): Promise<user> => request.get(`https://users-service/${userId}`));

Jon Mellman • 4 years ago

Thanks, you're right! In the examples, I wanted to be more verbose to make it as obvious as possible that an `await` is happening, and that the HTTP request returns a `User`.

Dustin Schau • 4 years ago

Hi Jon!

Big fan of these articles lately, keep 'em up.

(Oh... and thanks for using Gatsby. Please feel free to reach out if we can ever help improve your experience 👍)

Jon Mellman • 4 years ago

Thanks Dustin, much appreciated!

Gatsby has been working solidly since I set it up 1.5 years ago. The other day I had to upgrade a handful of library versions and expected it to be a nightmare, but no issues at all! So, I appreciate the care y'all put into backwards compatibility :)

Cheers!