1

Here is a for loop written by Javascript. It is trying to apply queries for websql.

for (var i = 0; i < 10; i++){
    db.transaction(function (tx){
    tx.executeSql('INSERT INTO ProjSetsT (ProjID) VALUES (?);', [i]);
    });
}

The attempt is obvious, I tried to add values "0, 1, 2, ... 9" into column ProjID in table ProjSetsT. It does not work. I only got the last element, i.e. "9" inserted, but not the first eight numbers.

Is there any syntax mistakes?

Mengfei Murphy
  • 1,049
  • 3
  • 11
  • 16
  • 2
    Syntax mistakes would prevent it from running outright... WebSQL is an asynchronous API, you can't expect it to catch the right values this way. See [Web SQL Database + Javascript loop](http://stackoverflow.com/questions/4825455/web-sql-database-javascript-loop). Also, running multiple queries in one transaction is faster and actually guarantees the insertion order. Running each one in a separate transaction is a slow free-for-all with random ordering. – DCoder Sep 25 '12 at 15:38
  • 1
    Why not make one query? Where the value binded is a string built from the values in the for loop. – Austin Brunkhorst Sep 25 '12 at 15:39

3 Answers3

4

I think db.transaction might run asynchronously so that might be messing it up for you. Have you tried to move your for loop inside the transaction?

db.transaction(function (tx){
    for (var i = 0; i < 10; i++){
        tx.executeSql('INSERT INTO ProjSetsT (ProjID) VALUES (?);', [i]);
    }
});
Neil Kennedy
  • 593
  • 1
  • 5
  • 12
  • You are right. And I think this is the most straight forward method to do it though other people's advices all work. That's why I put yours as the answer. – Mengfei Murphy Sep 26 '12 at 15:43
2

Every function you pass as an argument shares the same reference to i, so every new function object's i value gets incremented. given the async context, i will have reached its max size before the first function you create inside the loop gets called

You can fix it using a closure:

for (var i = 0; i < 10; i++)
{
    db.transaction((function(privateI)
    {//privateI is unique for every function object
        return function (tx)
        {
            tx.executeSql('INSERT INTO ProjSetsT (ProjID) VALUES (?);', [privateI]);
        };
    })(i));//pass current value here
}
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
1

You have several functions referencing the same i variable, which ends up as 10.

You need a new varible scope for each function.

for (var i = 0; i < 10; i++){
    db.transaction(makeHandler(i));
}

function makeHandler(j) {
    return function (tx){
        tx.executeSql('INSERT INTO ProjSetsT (ProjID) VALUES (?);', [j]);
    };
}

Now i is passed to makeHandler, which receives it as j.

Every time makeHandler is called, it returns a function that references its own local j varaible.

I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77