Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 233
w0f Avatar asked Jan 28 '23 21:01

w0f


1 Answers

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);
    }
}
like image 191
maxpaj Avatar answered Jan 30 '23 10:01

maxpaj