Вас по сути попросили свои Promise написать. Зациклить там не получится, т.к. чейнинг тогда не будет работать (как у вас например).
Вот простенький вариант того, как будет работать. Т.е. собираем все функции сразу, сохраняем все хэндлеры в массиве handlers, и затем уже вызываем асинхронное ожидание чего-то.
var def = {
handlers: [],
when : function (func) {
console.log ('start async');
func.call(def, def.done);
waiter();
function waiter() {
setTimeout (function () {
if (def.result) {
def.resolve(def.result);
}
else {
waiter();
}
}, 500);
}
return def;
},
resolve: function(result) {
console.log('start resolving');
var _result = result;
def.handlers.forEach(function(handler) {
_result = handler(result);
});
def.result = _result;
},
then : function (func) {
def.handlers.push(func);
return def;
},
done : function (result) {
def.result = result;
}
};