6

I am using following code to fetch hierarchical data from Web SQL Database:

...
function getResult(query, data, callback){
    db.transaction(function(tx) {
        tx.executeSql(query, data, function(tx, result) {
        callback(result);
        });
    });
}

function findChildren(id){
    getResult("SELECT * FROM my_table WHERE parent_id=?", [id], function(result){
        for (var i = 0, item = null; i < result.rows.length; i++) {
            item = result.rows.item(i);
            data.push(item);
            findChildren(item.id);
        }
    });
}
var data = Array();
getResult("SELECT * FROM my_table WHERE name like ?", ["A"], function(result){
    for (var i = 0, item = null; i < result.rows.length; i++) {
        item = result.rows.item(i);
        data.push(item);
        findChildren(item.id);
    }
});
...

How can I detect if the execution has been completed?

6
  • 1
    Without a callback in findChildren there is no chance. Also, you are calling them in a loop, too, which complicates things. Have you looked into Promises? Commented Nov 19, 2012 at 23:49
  • Well, what is the real problem? What are you trying to do? Commented Nov 20, 2012 at 9:33
  • Promises seems to be the solution, I am trying this out. Commented Nov 20, 2012 at 9:41
  • @phant0m I push all the data in an array and want to use that at the end. Commented Nov 20, 2012 at 9:42
  • 1
    As you haven't given much detail about the implementation it's difficult to say for sure, but it seems like you could do all this with a single more sophisticated SQL query - cutting out the current problem, reducing traffic, and improving performance. Commented Nov 21, 2012 at 0:05

1 Answer 1

3

Use a callback for findChildren and a counter for open transactions:

function findChildren(id, callback){
    getResult("SELECT * FROM my_table WHERE parent_id=?", [id], function(result){
        var results = [],
            results.finished = 0;
            len = result.rows.length;
        for (var i = 0; i < len; i++) (function(i) {
            var item = result.rows.item(i);
            ...
            ...
            findChildren(item.id, function(result) {
                results[i] = result;
                if (++results.finished == len)
                    callback(results);
            });
        })(i);
    });
}

getResult("SELECT * FROM my_table WHERE name like ?", ["A"], function(result){
    var results = [],
        results.finished = 0, 
        len = result.rows.length;
    for (var i = 0; i < len; i++) (function(i) {
        var item = result.rows.item(i);
        ...
        ...
        findChildren(item.id, function(result) {
            results[i] = result;
            if (++results.finished == len) {
                // now results contains a nice tree of arrays with children ids
                // do something with it
            }
        });
    })(i);
});

Promises will abstract the counter and simplify the callback handling. Also, as your two queries are very similiar, you might want to abstract them in a common function, too.

Sign up to request clarification or add additional context in comments.

1 Comment

@XiaodongLiang Admittedly, state of the art 5 years later are promises, async/await and Promise.all :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.