Sequential function call in JavaScript I've created this code which can call functions/ajax requests or pieces of code sequentially, using jQuery. The code not only can call functions/ajax requests or pieces of code sequentially but it also tracks when those calls fail or succeed and when the code fails it stops and doesn't exectue the rest of the queue.
(Bold italic are the names of the queues)
In my example i've 5 timeouts who get queued, the 2 first share a queue named first (1 and 1b) get executed at the same time and when those 2 finish and succeed(fire resolve) the next on the queue gets executed (next in queue is two which contains only 1 timeout). After two gets executed and succeed the third gets executed. I've coded in a way that the third fires a reject which changes the state of promise to reject(fails the request) and thanks to that the last timeout doesn't get called(to simulate a failed ajax request).

I know the code is pretty messy (it's my first version).  I would like some ideas on how I could structure this better or reduce the code considerably.

A problem I have with my code is that when I add a setTimeout, I have to include the deferred.resolve() in it.  I don't see a way around this.  Does anyone have an idea how to resolve this problem?

Code: http://jsfiddle.net/g55PC/

function myqueue(){
    var myself=this;
    var ord=[];// contains names used in promiseArr
    var funcArr=[];// contains setTimeout functions
    var me = $(document);

    this.add = function (func, name) {
        if (typeof funcArr[name] !== "object") funcArr[name] = [];

        funcArr[name].push(func);
        if($.inArray(name, ord)==-1){
            ord.unshift(name);
        }

    }

    this.call= function (name) {

        me.queue("deferQueue", function () {

            var promiseArr=[];

            for(func in funcArr[name]){
                promiseArr[func]=(function(){
                    var dfd = new jQuery.Deferred();
                    funcArr[name][func](dfd);
                    return dfd.promise();   
                })();
            }

            $.when.apply($,promiseArr).then(function () {
                console.log("Success "+name);
                me.dequeue("deferQueue");
            }, function () {
                console.log("Fail "+name);
            });
        });
    }
    this.start = function () {
        while(ord.length&gt;0) {
            this.call(ord.pop());
        }
        me.dequeue("deferQueue");
    }
};
myPlugin = new myqueue();
myPlugin.add(function (dfd) {
    setTimeout(function () {
        $("#result").append("&lt;div&gt;1&lt;/div&gt;");
        //console.log("1");
        dfd.resolve();
    }, 2000);
}, "first");//first = queue Name
myPlugin.add(function (dfd) {
    setTimeout(function () {
        $("#result").append("&lt;div&gt;1b&lt;/div&gt;");
        //console.log("1b");
        dfd.resolve();
    }, 1000);
}, "first");//first = queue Name
myPlugin.add(function (dfd) {
    setTimeout(function () {
        $("#result").append("&lt;div&gt;2&lt;/div&gt;");
        //console.log("2");
        dfd.resolve();
    }, 1000);
}, "second");//second = queue Name 
myPlugin.add(function (dfd) {
    setTimeout(function () {
        $("#result").append("&lt;div&gt;3&lt;/div&gt;");
        //console.log("3");
        dfd.reject();
    }, 500);
}, "third");//third = queue Name 
//forth will not be fired since third failed
myPlugin.add(function (dfd) {
    setTimeout(function () {
        $("#result").append("&lt;div&gt;4&lt;/div&gt;");
        //console.log("4");
        dfd.resolve();
    }, 3000);
}, "forth");//forth = queue Name 

myPlugin.start();
I like the idea of your code but you defenitely have some bugs and convention issues that should be dealt with:


Major bug: call does not remove funcArr[name] after iterating them so if you add something to the "first" queue and call the first queue, adding something to the first queue will still have the functions from before you called the queue earlier. I created a (demo of the issue); as you see the alert will be shown twice as funcArr[name] is never emptied 
You're storing keys (function names) in the array funcArr. funcArr should be a hash object rather than an array.
You're using for..in on an array (why this is bad) and moreover, the variable func will be global. Use a regular for loop instead here. I'd recommend using $.each here. With $.each you'd write the loop

$.each(funcArr, function(i, fn) {
    var dfd = $.Deferred();
    fn(dfd);
    promiseArr.push(dfd.promise()); 
});

You're module pattern seems off... 1) its common convention that a class name should be capitalized, ie MyQueue, 2) theres no real reason to use the this keyword if you're not planning to add these functions on prototype, 3) In this.start your line this.call(ord.pop()); is a bit confusing.
As you were not making use of prototype in your function I adapted your code to use the "module pattern". This allows your module to be created without the new keyword whereas before it would of caused major issues.


Here's how I would write your queue. I added comments on most of my cahnges

function myqueue(){
    var ord=[];
    var funcHash = {}; // Use a hash as you're using keys rather than indicies
    var me = $(document);//(minor)convention would be to name this $doc

    var plugin = {
        add: function (func, name) {
            if(!funcHash.hasOwnProperty(name)) {//name does not exist yet
                funcHash[name] = [];
                ord.unshift(name);
            }
            funcHash[name].push(func);//now just queue the function         
        },

        call: function (name) {
            me.queue("deferQueue", function () {    
                var promiseArr=[];
                var funcArr = funcHash[name];

                //funcArr is a hash of arrays don't use for in
                //also func was a global variable!]

                $.each(funcArr, function(i, fn) {
                     var dfd = new jQuery.Deferred();
                     fn(dfd);
                     promiseArr.push(dfd.promise()); 
                });

                //I assume you want to remove the functions after you call them so requeing the same name doesn't add to the old queue
                delete funcHash[name];

                $.when.apply($,promiseArr).then(function () {
                    console.log("Success "+name);
                    me.dequeue("deferQueue");
                }, function () {
                    console.log("Fail "+name);
                });
            });
        },

        start: function () {
            while(ord.length&gt;0) {
                plugin.call(ord.pop());
            }
            me.dequeue("deferQueue");
        }
    };

    return plugin;
};


http://jsfiddle.net/g55PC/2/

As for the second question of having to do the .resolve() in the timeout, you may want to consider adding a helper to your myqueue module along the lines of

//helper function for automatically managing a delay using timeout
addDelayed: function(fn, name, delay) {
    this.add(function(dfd) {
        setTimeout(function () {
            fn(dfd);
            dfd.resolve();
        }, delay || 250);
    }, name);
}


So your old pattern code be reduced to just:

myPlugin.addDelayed(function (dfd) {
    $("#result").append("&lt;div&gt;1&lt;/div&gt;");
}, "first", 1000);