jQuery Deferred Queue

HTML

<div id="log"></div>

JavaScript

this.log = function(message, delay) {
  var asyncLog = $,Deferred;
  console.log('3: log running with message=' + message + ' and delay=' + delay);
  setTimeout(
    function() {
      $('#log').append('<p>' + message + '</p>');
      asyncLog.resolve(delay);
    },
    delay
  );
  return $.when(asyncLog).promise();
};

var Queue = function() {
    var lastPromise = null;

    this.add = function(obj, method, args, context) {
      console.log('18: calling ' + method + ' with args=' + args[0] + ', ' + args[1]);
        var methodDeferred = $.Deferred();
        var queueDeferred = this.setup();
        if(context === undefined) { context = obj; }

        // execute next queue method
        queueDeferred.done(function() {


            // call actual method and wrap output in deferred
            setTimeout(function() {
                obj[method].apply(context, args);
                methodDeferred.resolve();
            }, 100);


        });
        lastPromise = methodDeferred.promise();
    };

    this.setup = function() {
        var queueDeferred = $.Deferred();

        // when the previous method returns, resolve this one
        $.when(lastPromise).always(function() {
            queueDeferred.resolve();
        });

        return queueDeferred.promise();
    }
};

var q = new Queue();
q.add(this, 'log', ['one', 4000]);
q.add(this, 'log', ['two', 3000]);
q.add(this, 'log', ['three', 2000]);
setTimeout(function(){
    q.add(this, 'log', ['four']);
}, 2000);