Search code examples
javascriptnode.jspromisees6-promise

Queuing Promises (ES6)


I'm writing a NodeJS service that requests data from APIs. Under load, I don't want to hammer the API with potentially hundreds of simultaneous requests, so I am trying to queue up the requests so they are executed one-by-one and with a delay between them.

const request = require( 'request' );
class WebService {
  constructor() {
    this.RequestQueue = [];
  }

  _Get( uri, options, reply ) {
    return new Promise( ( resolve, reject ) => {
      request.get( uri, options, ( err, resp, body ) => {
        if ( err )
          reject( err );

        reply( resp );
        resolve( resp );
      } );
    } );
  }

  async onRequest( data, reply ) {
    this.RequestQueue.push( this._Get( data.uri, data.opts, reply ) );
  }

  async execute() {
    while( this.RequestQueue.length > 0 ) {
      var current = this.RequestQueue.shift();
      await current();
      await Utils.Sleep(5000); //promise that resolves after 5 seconds
    }
  }
}

Due to the nature of ES6 promises, they start executing when constructed, so this._Get() inside of the onRequest event returns a promise that is already executing. Is there a clean way to avoid this so that I can properly queue the request for later?


Solution

  • Try adding the request options to the queue instead of the actual request Promise:

    onRequest(data, reply) {
        this.RequestQueue.push({ 
            uri: data.uri, 
            opts: data.opts, 
            reply: reply 
        });
    }
    
    async execute() {
        while(this.RequestQueue.length > 0) {
            var current = this.RequestQueue.shift();
            await this._Get(current.uri, current.opts, current.reply);
        }
    }