Context
Let’s say we want to retrieve the information for a package on
npm. We might just initialy write this function:
async function getNpmPackage(name): Promise<NPMPackage> {
return await got(`https://registry.npmjs.org/${name}`).json();
}where we simply take a package name, and make a request to
npm every time we want the package information. However,
this can lead to unneccesary extra requests, since we may be repeating
calls to npm that we have made in the near past.
Using a closure to cache results
If we expect to be making the same request multiple times and we don’t expect the result to change between each identical request, we can cache the response of the first request, and then simply return that cached response on each subsequent request.
This might be the case in our context, for example, if we are retriving the information on the dependencies of different packages, and we expect many of these packages to be using the same dependencies. In this situation, we would benefit from caching the responses and avoid unneccesary extra requests.
To do this, we can write a closure that acts as a proxy between the
client making a request and the request actually being sent. In the code
below, getNpmPackageProxy() first declares
npmPackages as a cache in the enclosed function scope, and
then returns a function that takes a package name as a parameter, checks
to see if we have already made a request for that package name, if not,
makes the request and saves the result in the cache, and then returns
the result stored in the cache.
We then assign the result of calling
getNpmPackageProxy() to getNpmPackage(name).
We can the simply call getNpmPackage(name) exactly as we
were before, expect now we will first check the cache to see if we have
already made the request and can avoid the repeated call.
function getNpmPackageProxy(): (name: string) => Promise<NPMPackage> {
const npmPackages: { [packageName: string]: NPMPackage } = {};
return async (name: string) => {
if (!npmPackages[name]) {
npmPackages[name] = await got(
`https://registry.npmjs.org/${name}`
).json();
}
return npmPackages[name];
};
}
const getNpmPackage: (name: string) => Promise<NPMPackage> =
getNpmPackageProxy();