Problem creating a closure

S

shuchow

Hi, all. I'm using Webkit's Client-side Javascript functionality to
create an app. I have a object method where I'm trying to create a
closure:

getMessages: function() {

var container;
var transactionFunction = function (transaction) {
container = 'one';

var successCallback = function(tx, result) {
container = 'two';
}

var errorCallback = function(tx, result) {}

transaction.executeSql('SELECT * FROM message', [], successCallback,
errorCallback);
}

this.systemDB.transaction(transactionFunction);
return container;
}

For those not familiar with the client-side js api, there is a
database connection (this.systemDB in this case) that takes a function
(transactionFunction) that executes sql. Any calls to transcation.
executeSql is part of the transaction. The executeSql function
requires two call backs - one for success and one for failure.

From what I understand, the container variable should be in scope at
least when it's set to 'one' and when it's set to 'two.' However,
it's not being set. When the function is called, it returns
undefined. Any ideas?

(what I'm ultimately trying to do is to return the result variable
back to the caller of this getMessages function)

Thanks for any insight.
 
R

RobG

Hi, all.  I'm using Webkit's Client-side Javascript functionality to
create an app.  I have a object method where I'm trying to create a
closure:

getMessages: function() {

        var container;
        var transactionFunction = function (transaction) {
                container = 'one';

                var successCallback = function(tx, result) {
                        container = 'two';
                }

                var errorCallback = function(tx, result) {}

                transaction.executeSql('SELECT * FROM message', [], successCallback,
errorCallback);
        }

        this.systemDB.transaction(transactionFunction);
        return container;

}

For those not familiar with the client-side js api, there is a
database connection (this.systemDB in this case) that takes a function
(transactionFunction) that executes sql.  Any calls to transcation.
executeSql is part of the transaction.  The executeSql function
requires two call backs - one for success and one for failure.

From what I understand, the container variable should be in scope at
least when it's set to 'one' and when it's set to 'two.'  However,
it's not being set.  When the function is called, it returns
undefined.  Any ideas?

Try the iPhone web dev group, they mess around with this stuff a bit:

<URL: http://groups.google.com.au/group/iphonewebdev?hl=en >

There's a thread here that may be of interest:

<URL:
http://groups.google.com.au/group/i...en&lnk=gst&q=database+HTML+5#a45d7fa83da87d0f
 
S

shuchow

Thanks a lot for the tip and the resources. It does sound plausible
that it's a race condition. I'll check the iPhone web dev group for
more clues.
 
S

Shu Chow

After some fiddling and more research, I found out that Conrad was
100% right. The executeSql command runs asynchronously, and it
doesn't look like there's a way to make it run synchronously.

Is there a way I can rewrite the entire function and the callbacks so
that getMessages doesn't return anything until "container" is
populated with the result set?
 
T

Thomas 'PointedEars' Lahn

Shu said:
After some fiddling and more research, I found out that Conrad was
100% right. The executeSql command runs asynchronously, and it
doesn't look like there's a way to make it run synchronously.

Is there a way I can rewrite the entire function and the callbacks so
that getMessages doesn't return anything until "container" is
populated with the result set?

Yes, but I don't think you have to rewrite the callbacks. Asynchronous
(what you have, in pseudo code):

var transaction = {
executeSql: function(query, whatever, fSuccess, fError) {
var x = new XHR();

x.open(method, url, true);

x.onreadystatechange = function() {
if (x.readyState == 4)
{
if (isSuccessful(x.status))
{
fSuccess(x);
}
else
{
fError(x);
}
}
};

x.send(...);
}
};

Asynchronous or synchronous (what you ask for, in pseudo code):

var transaction = {
executeSql: function(query, whatever, fSuccess, fError, bAsync) {
var x = new XHR();

if (typeof bASync == "undefined")
{
bAsync = true;
}
else
{
bAsync = !!bAsync;
}

x.open(method, url, bAsync);

var f = function() {
isSuccessful(x.status) ? fSuccess(x) : fError(x);
};

if (bAsync)
{
x.onreadystatechange = function() {
if (x.readyState == 4)
{
f();
}
};
}

x.send(...);

if (!bAsync)
{
f();
}
}
}

Then call:

transaction.executeSql(
'SELECT * FROM message',
[],
successCallback,
errorCallback,
false);


HTH

PointedEars
 
S

Shu Chow

Thanks, but ajax is not what I'm doing.

executeSql is the function running asynchronously. It's an api
function to execute sql statements against the local database. I
don't define it. executeSql(theSqlStatment, variablesInTheStatement,
successCallback, errorCallback).
 
T

Thomas 'PointedEars' Lahn

Shu said:

Thanks for proper quoting next time.

but ajax is not what I'm doing.

Are you sure? If yes, you could have been more precise; without context,
those callbacks are crying out for XHR, IMHO.
executeSql is the function running asynchronously.
It's an api function to execute sql statements against the local database.

Which can still be implemented with XHR if the DBMS provides a HTTP server.
man SOAP
I don't define it. executeSql(theSqlStatment, variablesInTheStatement,
successCallback, errorCallback).

Maybe you can use self-calling window.setTimeout() (or, if not
time-critical, window.setInterval()) to call another API function or access
a property provided by the API that yields the status of the SQL query. You
could then call window.clearTimeout() (or window.clearInterval(),
espectively), after which you populate the document with the retrieved data.


PointedEars
 
S

Shu Chow

Are you sure?  If yes, you could have been more precise; without context,
those callbacks are crying out for XHR, IMHO.
Which can still be implemented with XHR if the DBMS provides a HTTP server.
 man SOAP

I guess my crime is that I hit the delete button while posting my
message from Google. I didn't include my original statement where I'm
saying I'm using "Client-side Javascript." No, I'm not using any sort
of DBMS server, and callbacks and synchronicity are not exclusive to
xmlhttprequest. This has nothing to do with a connection back to the
server.

The psuedo original code I had:

getMessages: function() {

var container;
var transactionFunction = function (transaction) {
container = 'one';

var successCallback = function(tx, result) {
container = 'two';
}

var errorCallback = function(tx, result) {}

transaction.executeSql('SELECT * FROM message', [],
successCallback,
errorCallback);
}

this.systemDB.transaction(transactionFunction);
return container;

}
 
T

Thomas 'PointedEars' Lahn

This is not remotely what I posted. Learn to quote, please.
I guess my crime is that I hit the delete button while posting my
message from Google. I didn't include my original statement where I'm
saying I'm using "Client-side Javascript."

For suitable values of "Javascript", that is implied here; see the FAQ.
No, I'm not using any sort of DBMS server,

Where does your SQL-compatible database run, then?
and callbacks and synchronicity are not exclusive to xmlhttprequest.

I know that.
This has nothing to do with a connection back to the server.

Not even a *local* server?
The psuedo original code I had:
[...]

I have read it already, there is no point in reiterating.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top