Looping To Send Network Data in NodeJS

Lets say I have a message queue, it would be much longer in production

var mq = ["A","B","C"];

I want to send each message out over UDP BUT I need to rate limit it as to not overwhelm the receiver.

            while(mq.length)
            {
                limit.removeTokens(1,function(){

                    var m = mq.pop();
                    client.send(m,0,m.length,port,ip, function(err,bytes){
                        console.log("sent");
                    });
                });
            }

As I understand it, the while loop will block, and will not actually send out data. It actually ends up with a memory alloc error cause it keeps spinning up.

I tried using process.nextTick() but it ends up with a recursion error.

What is the proper way to go about this?

Thanks!

This is something that can be modeled with a simple queue. Here's an example:

var mq = ["A","B","C"];

// create a queue with the max concurrent jobs to run
// and a function that starts a new job
var queue = new Queue(5, function(item, callback){
    client.send(item, 0, item.length, ip, function(){
        // signal that we're done, and another item can start
        callback();
    });
});

// add an array of items to the queue
mq.forEach(queue.add);
function Queue(max, handler){
  var queueItems = [];

  // we keep a count of the number of unused job slots we have
  // when this is more than 0, a new job will start
  this.available = max;

  this.add = function(item){
      queueItems.push(item);
      process.nextTick(function(){
          this.maybeRunActions();
      }.bind(this));
  }.bind(this);

  // this will run actions if both:
  //  - we have actions to run
  //  - we have unused slots
  this.maybeRunActions = function(){
    while (this.available > 0 && queueItems.length > 0) {
       this.available -= 1;

       // call the handler passed to new Queue, which kicks of the job
       // and tells the queue when the job is complete
       handler(queueItems.shift(), function(){
           this.available += 1;
           this.maybeRunActions();
       }.bind(this));
    }
  }
}