SrgHartman
SrgHartman

Reputation: 651

Javascript: Traverse lists of lists asynchronously

I'm trying to traverse a javascript lists of lists.

The goal is to pass each item into a function and process it asynchronously. However it isn't working:

var tree = function (data, callback) {

    var data_position = 0;

    var iterate = function () {

        if (data_position<data.length) {
            if (Array.isArray(data[data_position])) {
                tree(data[data_position], callback);
                // If I uncomment these it will show all items but not ordered
                //data_position++;
                //iterate();
            } else {
                callback(data[data_position++], iterate);
            }
        }
    }

    iterate();
}


tree([1, 2, [100, 200, 300], 3, 4, 5, 6, 7, 8, 9], function (item, iterate) {
    setTimeout(function(){
        console.log('Item: ' + item);
        iterate();
    }, 1000);
})

The code stops at 300 instead of processing the rest of the tree.

If I uncomment those 2 lines above, I can print all items, but they don't show ordered. How can I fix this?

Upvotes: 1

Views: 64

Answers (2)

Jaanus Varus
Jaanus Varus

Reputation: 3573

This solution uses a second optional callback that allows the child iterating function tree to signal the parent tree to continue running once the child is finished.

It runs as expected with 1 second delay between every leaf element iteration.

var tree = function (data, callback, done) {
    var data_position = 0;
    var iterate = function () {
        if (data_position<data.length) {
            if (Array.isArray(data[data_position])) {
                tree(data[data_position++], callback, function() { iterate(); });
            } else {
                callback(data[data_position++], iterate);
            }
        } else if (done) {
            done();
        }
    }
    iterate();
};


tree([1, 2, [100, 200, 300], 3, 4, 5, 6, 7, 8, 9], function (item, iterate) {
    setTimeout(function(){
        console.log('Item: ' + item);
        iterate();
    }, 1000);
});

Upvotes: 2

misantronic
misantronic

Reputation: 1211

This should work:

var tree = function (data, callback) {

    var data_position = 0;

    var iterate = function () {

        if (data_position<data.length) {
            if (Array.isArray(data[data_position])) {
                tree(data[data_position], callback);
            }
            callback(data[data_position++], iterate);
        }
    }

    iterate();
}


tree([1, 2, [100, 200, 300], 3, 4, 5, 6, 7, 8, 9], function (item, iterate) {
    setTimeout(function(){
        if(!Array.isArray(item)) console.log('Item: ' + item);
        iterate();
    }, 1000);
})

Upvotes: 0

Related Questions