sune
sune

Reputation: 61

Defer Node.js HTTP requests if similar work already being done

I'm making a service which retrieves a photograph from a remote host and does some processing before passing it on to the client. It caches the retrieved source photo locally to avoid retrieving it again later on.

However, if there are several requests in rapid succession, the source image will not yet have been saved locally, and unnecessary retrievals are performed.

What is a nice approach to defer the incoming requests until the source image is cached, provided it's already currently being retrieved?

I'm currently using Node.js streams all the way from the inbound request stream, passing it through my caching and transformation logic, passing it to the outbound stream.

Upvotes: 1

Views: 145

Answers (1)

Marcos Casagrande
Marcos Casagrande

Reputation: 40394

You can cache the promise so all incoming requests to the same resource will only require one trip, avoiding flooding the database or some API.

const Cache = {};

function getPhoto(photoId) {

    let cacheKey = `photo-${photoId}`;
    let photoCache = Cache[cacheKey];

    if (photoCache instanceof Promise)
        return photoCache; //Return the promise from the cache

    let promise = new Promise((resolve, reject) => {

        if (photoCache) //Return the photo if exists in cache.
            return resolve(photoCache);

        return processPhoto(photoId).then(response => {
            //Override the promise with the actual response
            Cache[cacheKey] = response; 
            resolve(response);

        }).catch(err => { 
            Cache[cacheKey] = null; //We don't want the rejected promise in cache!
            reject();
        });

    });

    if (!photoCache)
        Cache[cacheKey] = promise; //Save the promise       

    return promise;
}

function processPhoto(photoId){

 return new Promise((resolve, reject) => {

      // Get the image from somewhere...
      // Process it or whatever you need

      //...
      resolve('someResponse');
 });

}
  • First request to a specific photo will perform the lookup, and will store the promise in the cache.
  • Second request comes in and if the photo from first request hasn't yet been retrieved, getPhoto will return the same promise, when the promise is resolved, both requests will get the same response.
  • Third request comes after the photo has been already retrieved, since the photo is cached it will just return the response.

Upvotes: 2

Related Questions