Mengfei Murphy
Mengfei Murphy

Reputation: 1089

Only the last run in a for loop in Javascript works

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?

Upvotes: 1

Views: 1581

Answers (3)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76413

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
}

Upvotes: 2

I Hate Lazy
I Hate Lazy

Reputation: 48771

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.

Upvotes: 1

Neil Kennedy
Neil Kennedy

Reputation: 603

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]);
    }
});

Upvotes: 4

Related Questions