2

I know that I cannot retrieve the value of transaction Synchronously. I Read that an alternative is to Callback the function. But I can't manage to do it.. here's a snippet where I inserted the second transaction inside a function.

for(...){
    db.transaction(function(tx) {
            tx.executeSql('SELECT ...', function(tx, results) {
                ...
                ...
                weight = weightRetrieve(month, year);
                calories = 0.9 * km * weighta;
            });
update+=xxx+calories+yyy;
} //for end

 $("#form").html(update).trigger('create'); 

And this is the second function:

function weightRetrieve(month, year) {
    db.transaction(function(tx) {
                tx.executeSql('SELECT weight,day,  ......etc) {

weight=results.rows.item(i).weight;
return weight;
}
}

I cutted out a lot of code, but the only problem I'm facing is that I cannot retrieve the weight from the second function neither this way or inside the first transaction cause if works async

It would be bad programming if I would store values with localStorage?

1 Answers1

2

As a general rule, if you are using asynchronous calls, trying to "return" a value isn't going to do you much good. The outer function has usually finished executing and returned the variable well before the inner asynchronous function has put any data in the variable, so you end up returning an empty variable. Additionally in your case, your "return" is returning from the anonymous function you passed to db.transaction rather than weightRetreive.

You instead need to pass in a callback function as a parameter, then call that callback function with the value once you have it.

For example:

function weightRetrieve(month, year, onSuccess) {
    db.transaction(function(tx) {
        tx.executeSql('SELECT weight,day,  ......etc', [], function(tx, results) {

            weight=results.rows.item(i).weight;
            onSuccess(weight);

        });
    });
}

Notice the addition of the parameter "onSuccess" as a callback function.

Because this is all in a for loop, you'll need to give each iteration the chance to finish and add its "calories" calculation to your final accumulated value before continuing. To do this you can create a function to call at the end of each iteration, which keeps track of the number of times it has been called and compares it to the length of the thing you're looping over before executing the final code:

var updateFinalValue = (function() {

    var numCalls = 0; // number of times the function has been called
    var totalIterations = thingYouLoopOver.length; // number of times the for loop will run
    var finalValue = 0; // total of all your "calories" calculations

    return function(additionalValue) {

        finalValue += additionalValue;

        if(++numCalls == totalIterations ) {

            document.getElementById("totalCalories").value = finalValue;
            doSomethingWithFinalValue(finalValue);
            // etc
        }
    };
})();

The syntax may look a bit weird if you're not overly familiar with javascript, but it's the inner function being returned that gets executed when you call "updateFinalValue". The outer function is evaluated immediately (notice the "();" right at the end - we're calling the outer function in-place) and serves purely to provide a scope for the inner function. This is known as a "closure", and among other things is a good way to encapsulate the variables rather than having to make them global.

You would then use this as follows:

for(...) {
    db.transaction(function(tx) {
        tx.executeSql('SELECT ...', [], function(tx, results) {
            ...
            ...
            weightRetrieve(month, year, function(weight) {

                var calories = 0.9 * km * weight;
                updateFinalValue(calories);

            });
        });
    });
}
  • Thanks for the comment, the problem is that the second piece of code (the transaction) is inside a for cycle and I need to perform some operation after the cycle have finished. I updated my original post with some new information – Gabriele Prestifilippo Aug 27 '14 at 10:51
  • Thanks, I never used this method, but I'm getting this error " Property 'updateFinalValue' of object [object Object] is not a function".Then, how can I pass a value to the outer function (the number of cycles)? – Gabriele Prestifilippo Aug 29 '14 at 12:00
  • Hmm, not sure why you're getting that error, do you have something else called updateFinalValue somewhere that's conflicting? As for setting the number of cycles, just do it in place. If that still doesn't make sense, can you post your for(...) and i'll re-edit? – Liam Dobson Aug 29 '14 at 14:38
  • No, also tried different names, but I temporary solved by using this function `function update(stringX){ finalValue+=stringX; count++; if(count==object.length){ $("#mydiv").html(finalValue).trigger('create'); finalValue=""; count=0; } }` – Gabriele Prestifilippo Aug 29 '14 at 17:51