Search code examples
javascriptnode.jspromisebluebird

Javascript function to handle concurrent async function more efficiently


Consider the following:

  • A web application that can have up to 100 concurrent requests per second
  • Each incoming request currently makes a http request to an endpoint to get some data (which could take up to 5 seconds)
  • I want to only make the http request once, i.e. I don't want to make concurrent calls to the same endpoint as it will return the same data
  • The idea is only the first request will make the http call to get the data
  • While this call is 'inflight', and subsequent requests will not make the same call and instead 'wait' for the first inflight request to complete.
  • When the initial http request for data has responded, it must respond to all calls with the data.
  • I am using Bluebird promises to for the async function that performs the http request.

I would like to create/use some sort of generic method/class that wraps the business logic promise method. This generic method/call will know when to invoke the actual business logic function, when to wait for inflight to finish and then resolve all waiting calls when it has a response.

I'm hoping there is already a node module that can do this, but can't think of what this type of utility would be called.

Something similar to lodash throttle/debounce, but not quite the same thing.

I could write it myself if it doesn't exists, but struggling to come up with a sensible name for this.

Any help would be appreciated.


Solution

  • You can implement a PromiseCaching, like:

    module.exports = function request(url) {
        if (caches[url]) return caches[url];
        var promise = req(url);
    
        return (caches[url] = promise);
    };
    
    var req = require('');
    var caches = {};
    

    EDIT:

    Let me be more explanatory:

    Here is not about caching of the responses, but about caching of promises. Nodejs is single threaded, that means, there no concurrent function calls, even when everything is async, at one point of time, runs only one peace of code. That means, there will be somebody first calling the function with the url y.com/foo, there will be no promise in the cache, so it will fire the GET request und will cache and return that promise. When somebody immediately calls the function with the same url, no more requests are fired, but instead the very first promise for this url will be returned, and the consumer can subscribe on done/fail callbacks. When the response is ready and the promise is fulfilled, and somebody makes the request with the same url, then again, it will get the cached promise back, which is already ready.

    Promise caching is a good technique to prevent duplicate async tasks.