Synchronizing async tasks Yes, I know there are plenty of libraries to get this done (Q, step, async), but only for learning I'm wondering if the following code is ok and usable or have major drawbacks and it is only usable at a small programs.

Usage:

var g = new Manager();

g.then ( 
    function() { 
        console.log("hello");
        setTimeout( function () { g.done("hello done") }, 2000 );
    }
);

g.start();

g.then ( 
    function() { 
        console.log("two");
        g.done ("two done");
    }
);

g.then ( 
    function(resp) { 
        console.log("I got: " + resp);
        setTimeout( function () { g.done("happy ending") }, 2000 );
    }
);

g.then ( 
    function(resp) { 
        console.log("last msg: " + resp);
        g.done();
    }
);


Class:

//...............................
// class Manager
//...............................
function Manager () { 
    this.functionList = [];
    this.allDone = false;
} // ()

//...............................
//...............................
Manager.prototype.then = function (fun) { 
    this.functionList.push (fun);
    if (this.allDone) { 
        this.allDone = false;
        this.done(this.previousResult);
        console.log ( "then(): continuing");
    } 

} // ()

//...............................
//...............................
Manager.prototype.done = function (prevRes) { 
    this.previousResult = prevRes;
    if ( this.where &lt;= this.functionList.length-2 ) { 
        this.where++;
        this.functionList [this.where](this.previousResult);
    } else { 
        this.allDone = true;
        console.log ( "done(): stopping because allDone: where=" + this.where + " and length = " + this.functionList.length);
    } 

} // ()

//...............................
//...............................
Manager.prototype.start = function () { 
    this.allDone = false;
    this.where=-1;
    this.done();
} // ()
Some points:


g.then(function() { … g.done ("two done");}) I (personally) don't like that signature, I'm more used to callbacks that get passed as parameters (g.then(function(done) { … done ("two done");})). They tend make the chained functions better reusable - in your case it might not matter since you're using dedicated function expressions anyway which are bound to g. And your signature simplifies argument handling in the Manager :-)
this.allDone = false; seems to be a misnomer for me. The way you're using it, it should rather be called startedAndNotRunning. Technically if you're initialising the empty list they are all done already :-)
This is highly confusing:

if ( this.where &lt;= this.functionList.length-2 ) { 
    this.where++;
    …


What happens to the last two functions? Nothing special. It better is written

this.where++;
if (this.where &lt; this.functionList.length) {
    …


Then the iterator variable (where) will become the length of the array after the "loop", which is the common behaviour. Yet, you cannot use done any more to [re]start the chain - you'd need to decrement where before. Therefore I'd recommend to restructure the methods to

function Manager () {
    …
    this.where = 0;
}
Manager.prototype.start = function () {
    // you might reset allDone and where
    this.next();
};
Manager.prototype.done = function (prevRes) { 
    this.previousResult = prevRes;
    this.where++;
    this.next();
};
Manager.prototype.next = function() {
    if (this.where &lt; this.functionList.length)
        this.functionList[this.where](this.previousResult);
    else { 
        this.allDone = true;
        console.log ( "done(): stopping at where=" + this.where + " with length = " + this.functionList.length);
    }
};
Manager.prototype.then = function (fun) { 
    this.functionList.push (fun);
    if (this.allDone) {
        this.allDone = false;
        this.start();
        console.log ( "then(): continuing");
    } 
};