2

I have a problem with the following code:

var data = {};

$('table tr').each(function() {
  var uid = $('td a', $(this)).attr('href').split('=')[1];

  TTDB.transaction(
    function (tx) {
        tx.executeSql("SELECT id FROM players WHERE uid = ?;", [uid], function (txSub, results) {
          data[uid] = results.rows.item(0).id;
        }, TTDBerrorHandler);
    }
  );
});

$('#member tbody tr').each(function() {
  var uid = $('td a', $(this)).attr('href').split('=')[1];

  console.log(uid); // Returns correctly 1643 as shown below
  console.log(data); // Returns whole object correctly
  console.log(data['1643']); // Returns **undefined**
  console.log(data[uid]); // Returns **undefined**
  console.log(uid); // uid is still correctly set to 1643

  /* Following from Safari console
  1643
  Object
    156: 1
    217: 17
    295: 138
    579: 136
    764: 139
    774: 142
    816: 144
    826: 14
    955: 73
    1096: 137
    1133: 13
    1134: 141
    1232: 140
    1321: 11
    1643: 31
    2307: 143
    __proto__: Object
  undefined
  undefined
  1643
  */
});

Here is a test set that works as it should.

var test = {};
test[156] = 1;
test[1643] = 31;

var testUid = 1643;

console.log(test);
console.log(test['1643']); // Returns correctly 31 as shown below
console.log(test[testUid]); // Returns correctly 31 as shown below

/* This is from Safari console
Object
  156: 1
  1643: 31
  __proto__: Object
31
31
*/

As basically identical test set works, I guess the problem has something to do with local database's asynchronous operation, but I just can't figure out how to fix this...

UPDATE: To clarify my problem/what I'm trying to achieve.

For example if I have a table, which I iterate through and then want to add some fields with data from database.

<table>
  <tr><td class="uid">123<td></tr>
  <tr><td class="uid">234<td></tr>
</table>

Then I would want to add new columns to it:

$('table tr').each(function() {
  var uid = $('td.uid', $(this)).text();

  TTDB.transaction(
    function (tx) {
        tx.executeSql("SELECT id FROM players WHERE uid = ?;", [uid], function (txSub, results) {
          // Problem is that because this transaction is asynchronous $(this) is 
          // not defined when this gets executed.
          $(this).append('<td class="id">' + id + '</td>'); 
        }, TTDBerrorHandler);
    }
  );
});
Damiqib
  • 1,067
  • 2
  • 13
  • 23
  • Object keys shouldn't start with a number. – ldiqual Aug 16 '12 at 20:54
  • have you tried `uid.trim()?` long shot, but you never know... – Elias Van Ootegem Aug 16 '12 at 21:03
  • @user1600680: [Because the specification says so](http://stackoverflow.com/a/2026760/646960). – ldiqual Aug 16 '12 at 21:13
  • @LoïsDiQual: The specification does not say that Object keys can't start with a number. It says that valid identifiers can't start with one. Object keys can be anything that can be converted to a string, so `data['1643']` and `data[1643]` are both valid and equal. If object keys couldn't start with a number, then Arrays would not work. – gray state is coming Aug 16 '12 at 21:23
  • @user1600680: you're right, my bad ;) I learned something today. – ldiqual Aug 16 '12 at 21:41

2 Answers2

1

If you change your log to to use JSON.stringify you will see that the object is empty.

console.log(uid);
console.log(JSON.stringify(data)); // Returns empty object

Using JSON.stringify forces the console to read the whole object immediately instead of later when you expand the object in the console.

You should put your logging code in the tx.executeSql callback to log the individual items after the response comes.

gray state is coming
  • 2,107
  • 11
  • 20
  • You're right: with JSON.stringify the object is empty. Could you clarify your last sentence? – Damiqib Aug 16 '12 at 22:35
  • @Damiqib: The reason that the object is empty is that the `executeSql` is an "asynchronous" request. This means that it doesn't block any code after it from running. Any code that operates on the response needs to be inside the callback. Basically the flow of code continues inside the callback instead of directly after the `tx.executeSql` call. – gray state is coming Aug 16 '12 at 23:09
0

Put the invocation of the code from this your callback

$('#member tbody tr').each(function() {...

inside the callback of executeSql() function and get rid of second $.each() at all.

So for each fetched row of data you'll update the appropriate row of HTML table.

UPDATE: Code example.

$('table tr').each(function() {
  var uid = $('td a', $(this)).attr('href').split('=')[1],
  tr$ = $(this);
  TTDB.transaction(
    function (tx) {
        tx.executeSql("SELECT id FROM players WHERE uid = ?;", [uid], function (txSub, results) {
          // access tr$ here...
          // $('td', tr$).each(function() { var td$ = $(this); /* ... */ });
          data[uid] = results.rows.item(0).id;
        }, TTDBerrorHandler);
    }
  );
});
Eugene Naydenov
  • 7,165
  • 2
  • 25
  • 43
  • This won't work because transaction is asynchronous -> $(this) is not defined when queries are executed... I originally created the second .each() to come around this problem, but still no bonus. – Damiqib Aug 16 '12 at 22:23
  • If I do this: tr$ = $(this); TTDB.transaction( function (tx) { tx.executeSql("SELECT id, att, def FROM players WHERE uid = ?;", [uid], function (txSub, results) { console.log(tr$); }, TTDBerrorHandler); } ); There's right amount of log events, but they all have the content of the last tr in table – Damiqib Aug 16 '12 at 22:55