I recently had an interesting requirement in a test environment where I needed to simulate actions at varied (random) intervals in a node back-end. They needed to be sequentially executed, but queued so I could fire and move on. Using a typical timeout/interval here wouldn't work, since if I set a timeout for fn1 to execute after 500ms and then set a timeout for fn2 to execute after 250ms, fn2 would execute before fn1, which was not desired.To solve this, I created a queue object that executes queued commands sequentially. It works perfectly for my scenario, but I was wondering if there were any opportunities for improvement. I realize I should probably be checking input parameters to make sure the passed in function is indeed a function, as well as the delay being a number. Maybe there are other opportunities for improvement. Let me know!var TimerQueue = (function () {    var timers = [];    var running = false;    var currentInterval;    var currentTimer;    this.addTimer = function (fn, delay) {        timers.push({fn: fn, delay: delay});        function exec() {            currentTimer.fn();            clearInterval(currentInterval);            if (timers.length > 0) {                currentTimer = timers.shift();                currentInterval = setInterval(exec, currentTimer.delay);            } else {                running = false;            }        }        if (!running) {            running = true;            currentTimer = timers.shift();            currentInterval = setInterval(exec, currentTimer.delay);        }    };    this.clear = function () {        if (currentInterval) {            clearInterval(currentInterval);        }        timers = [];        running = false;    };    return this;});Usage:var queue = new TimerQueue();queue.addTimer(function () { console.log('1st') }, 500);queue.addTimer(function () { console.log('2nd') }, 250);
Time-delayed function queue
javascript;node.js;queue
You can still use setTimeout. You just need to wrap it in a function and recursively call that function from within the timer callback while tasks still exist in the queue.Since what you need to do is schedule a task to run once after a delay, setTimeout is a better choice. Remember that setInterval runs the callback multiple times. If you don't clear it at the right time, you might face a callback running more than once.The presence of the timer ID is an indicator that a task is scheduled to run. No need for a running flag. Additionally, clear timer functions don't null references, you need to do it manually.A quick way to clear an array without assigning it another array is to set its length to 0.Prefer just using a function declaration when creating a constructor. It's simpler. Also, there's little benefit using private variables. It only forces you to define methods on the instance instead of the prototype which makes it not ideal. Methods should be on the prototype.Here's my take on it. Untested, but should work the same in theory:function TimerQeueue(){  this.currentTimer = null;  this.tasks = [];}TimerQueue.prototype.addTask = function(callback, delay){  this.tasks.push({ callback: callback, delay: delay });  // If there's a scheduled task, bail out.  if(this.currentTimer) return;  // Otherwise, start kicking tires  this.launchNextTask();};TimerQueue.prototype.launchNextTask = function(){  // If there's a scheduled task, bail out.  if(this.currentTimer) return;  var self = this;  var nextTask = this.tasks.shift();  // There's no more tasks, clean up.  if(!nextTask) return this.clear();  // Otherwise, schedule the next task.  this.currentTimer = setTimeout(function(){    nextTask.callback.call();    self.currentTimer = null;    // Call this function again to set up the next task.    self.launchNextTask();  }, nextTask.delay);};TimerQueue.prototype.clear = function(){  if (this.currentTimer) clearTimeout(this.currentTimer);  // Timer clears only destroy the timer. It doesn't null references.  this.currentTimer = null;  // Fast way to clear the task queue  this.tasks.length = 0;};