6

i have this code:

    function getData(){
        db.transaction(function(tx){
            tx.executeSql('SELECT * from q', [], function(tx, result){
                var q = [];
                for (var i=0; i < result.rows.length; i++) {
                    q.push(result.rows.item(i));
                };
                console.log(q.length);  // 3
                returnData(q);
            });
        });
    }

    function returnData(data){
        console.log(data.length); // 3
        return data;
    }

   var q = getData(); // undefined

and it don't work as expected (it don't return anything). A assume that happened, because db.transaction work asynchronous, but i'm using callback to return data. Can somebody explain why it doesn't work and how to fix that?

nukl
  • 10,073
  • 15
  • 42
  • 58

2 Answers2

7

The standard way to do this is to include your own callback, like this:

function getData(callback){
    db.transaction(function(tx){
        tx.executeSql('SELECT * from q', [], function(tx, result){
            var q = [];
            for (var i=0; i < result.rows.length; i++) {
                q.push(result.rows.item(i));
            };
            console.log(q.length);  // 3
            callback(returnData(q));
        });
    });
}

function returnData(data){
    console.log(data.length); // 3
    return data;
}

getData(function(q) {
    /* do something with q */
});
Ben Lee
  • 52,489
  • 13
  • 125
  • 145
  • so, there is no way, to put that array in a variable outside async function? – nukl Aug 25 '11 at 21:26
  • @nukl: You are able to assign the values to variables in any higher scope (e.g. to global variables), but this does not help you. The important point when using callbacks is *when* the data is accessed. If you access the variable *before* the callback was executed (and the value was set), you get wrong or no data. There are perfectly valid use cases for assigning the response to other variables, outside the callback, but you have to be aware of the implications of making asynchronous calls. – Felix Kling Aug 25 '11 at 21:30
  • @nukl, not unless you want to use CoffeeScript (a to-javascript compiled language): http://jashkenas.github.com/coffee-script/ – Ben Lee Aug 25 '11 at 21:30
  • Thanks,got it. btw, @Ben Lee, `callback(returnData(q));` needs to be changed to `callback(q)`, right? – nukl Aug 25 '11 at 21:37
  • @nukl, it depends on what you want. I assumed that "returnData" was a function that did more post-processing on the result before passing it back to your callback. But if returnData is not necessary, then you can just do `callback(q)`. It depends on your needs. – Ben Lee Aug 25 '11 at 21:40
0

You don't return the result of any async action, instead you listen for it.

In your code returnData does return the data, but the you dont do anything with the result, it's discarded. Instead, you should use your own callback.

function getData(callback){
    db.transaction(function(tx){
        tx.executeSql('SELECT * from q', [], function(tx, result){
            var q = [];
            for (var i=0; i < result.rows.length; i++) {
                q.push(result.rows.item(i));
            };
            console.log(q.length);  // 3
            callback(q);
        });
    });
}

var q;
getData(function(data) {
    console.log(data.length); // 3
    console.log(data);
    doStuffWith(data);
    q = data;
});
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337