4

I'm attempting to pass a function an array that should run through a loop and call a db.transaction for each incremented SQL statement.

function updateColorData (colorArray) {
    for (var i=0; i<colorArray.length; i++) {
        var sql = 'INSERT INTO SPColorData (color) VALUES (\''+colorArray[i]+'\')';
        if (i < colorArray.length-1) {
            db.transaction(function (tx) {tx.executeSql(sql, [], gameOptionSuccess, errorCB)}, errorCB);
        } else {
            db.transaction(function (tx) {tx.executeSql(sql, [], colorDataQuery, errorCB)}, errorCB);
        }
    }
}

As a test I'm calling the updateColorData function passing in an array like this

['one', 'two', 'three', 'four']

but when I have the database read back the information it received I'm getting

['four', 'four', 'four', 'four']

I realize that calling 4 database transactions in a loop like this is not the most efficient method but I'm not sure why this isn't working or what other method to try.

Thanks!

6
  • Can you explain which library you're using to execute queries from client side? Commented Jan 17, 2015 at 17:19
  • I'm developing for iOS using SQLite with Cordova framework. Is that the information you needed? Commented Jan 17, 2015 at 17:22
  • How do JavaScript closures work? + Exploits of a Mom (also known as: SQL injection) Commented Jan 17, 2015 at 17:23
  • Thanks. However could you explain what colorDataQuery and gameOptionSuccess do? They are callBack functions. Commented Jan 17, 2015 at 17:23
  • gameOptionSuccess is empty right now but colorDataQuery just calls a Select query that re-renders out the javascript array I have that stores the data from the database. Commented Jan 17, 2015 at 17:27

1 Answer 1

4

You need to create a new scope for i before you call the database function; try this:

function updateColorData (colorArray) {
    for (var i=0; i<colorArray.length; i++) {
        (function(i){
            var sql = 'INSERT INTO SPColorData (color) VALUES   (\''+colorArray[i]+'\')';
            if (i < colorArray.length-1) {
                db.transaction(function (tx) {tx.executeSql(sql, [], gameOptionSuccess, errorCB)}, errorCB);
            } else {
            db.transaction(function (tx) {tx.executeSql(sql, [], colorDataQuery, errorCB)}, errorCB);
            }
        })(i);
    }
}

That creates an individual function scope for each value of i, using an anonymous function. You need to do this because the for loop in your original example keeps updating i without waiting for your database function to return. So you need to create "safe" contexts for your database functions to run without the for loop changing the value of i, and that's exactly what the anonymous functions provide.

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

2 Comments

Could you please explain to why this works and the posted example won't?
Tried to explain in more depth.

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.