Q is a very complex promise library in terms of implementation because it aims to support pipelining and RPC type scenarios. I have my own very bare bones implementation of the Promises/A+ specification here.
In principle it's quite simple. Before the promise is settled/resolved, you keep a record of any callbacks or errbacks by pushing them into an array. When the promise is settled you call the appropriate callbacks or errbacks and record what result the promise was settled with (and whether it was fulfilled or rejected). After it's settled, you just call the callbacks or errbacks with the stored result.
That gives you aproximately the semantics of done
. To build then
you just have to return a new promise that is resolved with the result of calling the callbacks/errbacks.
If you're interested in a full explenation of the reasonning behind the development of a full on promise implementation with support for RPC and pipelining like Q, you can read kriskowal's reasonning here. It's a really nice graduated approach that I can't recommend highly enough if you are thinking of implementing promises. It's probably worth a read even if you're just going to be using a promise library.