title: ExpressJS queue requests
body: <p>I am looking to queue requests to ExpressJs so that only one request is processed on an endpoint at a time. I have found some examples of this: <a href="https://stackoverflow.com/questions/36083121/expressjs-backend-put-requests-into-a-queue">ExpressJS backend put requests into a queue</a></p>
  <p>It seems though they require a separate function for each endpoint. I am trying to create one function that allows me to pass a queue name, and then stack items in the specified queues.</p>
  <p>It is an API listening for requests, and upon receiving one will then execute a request to another online API before relaying the result back to the user through the original express endpoint. Ultimately I will then look to add some very basic caching for each endpoint, just to store a short JSON string for 3 seconds before expiring. That way it returns the cached string within the 3 second limit rather than fetch the data again from online.</p>
  <p>Here is as far as I got, I would be curious to hear if there are better ways:</p>
  <pre><code>//UI request -&gt; check cache -&gt; return response || call request then return response
  
  // Queue items on endpoint
  class QueueUnique {
    func;
    q;
    requestCache = [];
  
    constructor(func) {
      this.q = Promise.resolve();
      this.func = func;
    }
  
    add(request) {
      // Fetch all cached items related to the current endpoint queue
      const cachedItem = this.requestCache.find(
        (itm) =&gt; itm.queueName === request.queueName
      );
      // If the current request is within X seconds of the last successful requesst, return the cache
      // otherwise make a new request
      if (cachedItem &amp;&amp; new Date().getTime() - cachedItem.runtime &gt; 3000) {
        console.log(
          &quot;Cache is over 3 seconds old. Doing new request. Queue name: &quot; +
            request.queueName
          // no cahe, forward request:
          //seperate this in to function
          //res.sendResponse = res.send
          // res.send = (body) =&gt; {
          //  request.body = body
          //  this.updateCache(request);
          // res.sendResponse(body)
          //}
          //next()
        );
        this.updateCache(request);
      } else if (cachedItem) {
        console.log(&quot;Valid cache, return cache&quot;);
        // res.send(request.body)
        this.updateCache(request);
      } else {
        console.log(&quot;no cache&quot;);
        //continue as normal as if no cache
        // no cahe, forward request: Same as first run
        this.addToCache(request);
      }
  
      // Do I need to use await before setting datetime?
  
      //then cache
  
      // Set the current time as a value in the item Array
      request.runtime = new Date().getTime();
  
      const queuedFunc = this.queue(request);
      queuedFunc();
    }
  
    addToCache(request) {
      // Add the new item to the permanent cache
      this.requestCache.push(request);
    }
  
    updateCache(request) {
      // Update the permanent request cache entry
      const arrayIndex = this.requestCache.findIndex(
        (itm) =&gt; itm.queueName === request.queueName
      );
      this.requestCache[arrayIndex] = request;
    }
  
    queue(item) {
      return () =&gt; {
        this.q = this.q
          .then(() =&gt; this.func(item))
          .catch((err) =&gt; {
            console.log(err);
          });
        return this.q;
      };
    }
  }
  
  const response = (item) =&gt; {
    return new Promise((resolve) =&gt; {
      setTimeout(() =&gt; {
        console.log(&quot;say&quot;, item.payload);
        resolve();
      }, item.delay);
    });
  };
  
  const queue = [];
  function test(bar, payload) {
    if (!queue[bar]) {
      queue[bar] = new QueueUnique(response);
    }
    queue[bar].add(payload);
    console.log(queue);
    return queue;
  }
  
  test(&quot;te&quot;, {
    queueName: &quot;ping&quot;,
    payload: &quot;one&quot;,
    delay: 3000,
  });
  
  test(&quot;te&quot;, {
    queueName: &quot;ping&quot;,
    payload: &quot;one&quot;,
    delay: 3000,
  });
  
  test(&quot;te&quot;, {
    queueName: &quot;ping&quot;,
    payload: &quot;one&quot;,
    delay: 3000,
  });
  
  test(&quot;te2&quot;, {
    queueName: &quot;ping&quot;,
    payload: &quot;two&quot;,
    delay: 1000,
  });
  
  test(&quot;te2&quot;, {
    queueName: &quot;ping&quot;,
    payload: &quot;two&quot;,
    delay: 1000,
  });
  </code></pre>