Doing asynchronous programming, we often need to convert our synchronous approach to control flow. We need change our approaches to use callback / event based pattern.

One of the common situation is looping. This is my simple async version for “while” operator.

function asyncWhile(condition, func, callback) {
    var index = 0;
    var done = false;
    var iterator = {
        next: function() {        
            if (done) {
                return;
            }
            if (condition()) {
                index++;
                func(iterator);
            } else {
                done = true;
                callback(iterator.ex, iterator.result);
            }
        },
        break: function() {
            done = true;
            callback(iterator.ex, iterator.result);
        },
        iteration: function() {
            return index - 1;
        },
        ex: null, //contains exception
        result: null //contains result
    };
    iterator.next();
    return iterator;
};

The example of usage:

asyncWhile(function(){
    return i<10;
}, function(iterator){
    i++;
    if(i>=7)
    {    
        iterator.break();
        return;
    }
    console.log(iterator.iteration());
    iterator.next();
},function(ex, result){
    console.log('Finish');
});

With minor changes, this is the “for” version:

function asyncFor(total, func, callback) {
    var index = 0;
    var done = false;
    var iterator = {
        next: function() {        
            if (done) {
                return;
            }
            if (index < total) {
                index++;
                func(iterator);
            } else {
                done = true;
                callback(iterator.ex, iterator.result);
            }
        },
        break: function() {
            done = true;
            callback(iterator.ex, iterator.result);
        },
        iteration: function() {
            return index - 1;
        },
        ex: null, //contains exception
        result: null //contains result
    };
    iterator.next();
    return iterator;
};