1

I have a similar question here, but I thought I'd ask it a different way to cast a wider net. I haven't come across a workable solution yet (that I know of).

I'd like for XCode to issue a JavaScript command and get a return value back from an executeSql callback.

From the research that I've been reading, I can't issue a synchronous executeSql command. The closest I came was trying to Spin Lock until I got the callback. But that hasn't worked yet either. Maybe my spinning isn't giving the callback chance to come back (See code below).

Q: How can jQuery have an async=false argument when it comes to Ajax? Is there something different about XHR than there is about the executeSql command?

Here is my proof-of-concept so far: (Please don't laugh)

// First define any dom elements that are referenced more than once.
var dom = {};
dom.TestID = $('#TestID'); // <input id="TestID">
dom.msg = $('#msg'); // <div id="msg"></div>

window.dbo = openDatabase('POC','1.0','Proof-Of-Concept', 1024*1024); // 1MB

!function($, window, undefined) {
    var Variables = {}; // Variables that are to be passed from one function to another.

    Variables.Ready = new $.Deferred();
    Variables.DropTableDeferred = new $.Deferred();
    Variables.CreateTableDeferred = new $.Deferred();
    window.dbo.transaction(function(myTrans) {
        myTrans.executeSql(
            'drop table Test;',
            [],
            Variables.DropTableDeferred.resolve()
            // ,WebSqlError
        );
    });
    $.when(Variables.DropTableDeferred).done(function() {
        window.dbo.transaction(function(myTrans) {
            myTrans.executeSql(
                'CREATE TABLE IF NOT EXISTS Test' 
                + '(TestID Integer NOT NULL PRIMARY KEY'
                + ',TestSort Int'
                + ');',
                [],
                Variables.CreateTableDeferred.resolve(),
                WebSqlError
            );
        });
    });

    $.when(Variables.CreateTableDeferred).done(function() {
        for (var i=0;i < 10;i++) {
            myFunction(i);
        };
        Variables.Ready.resolve();
        function myFunction(i) {
            window.dbo.transaction(function(myTrans) {
                myTrans.executeSql(
                    'INSERT INTO Test(TestID,TestSort) VALUES(?,?)',
                    [
                        i
                        ,i+100000
                    ]
                    ,function() {}
                    ,WebSqlError
                )
            });
        };
    });
    $.when(Variables.Ready).done(function() {
        $('#Save').removeAttr('disabled');
    });
}(jQuery, window);

!function($, window, undefined) {
    var Variables = {};

    $(document).on('click','#Save',function() {
        var local = {};
        local.result = barcode.Scan(dom.TestID.val());
        console.log(local.result);
    });


    var mySuccess = function(transaction, argument) {
        var local = {};

        for (local.i=0; local.i < argument.rows.length; local.i++) {
            local.qry = argument.rows.item(local.i);
            Variables.result = local.qry.TestSort;
        }
        Variables.Return = true;
    };
    var myError = function(transaction, argument) {
        dom.msg.text(argument.message);
        Variables.result = '';
        Variables.Return = true;
    }

    var barcode = {};
    barcode.Scan = function(argument) {
        var local = {};

        Variables.result = '';
        Variables.Return = false;
        window.dbo.transaction(function(myTrans) {
            myTrans.executeSql(
                 'SELECT * FROM Test WHERE TestID=?'
                ,[argument]
                ,mySuccess
                ,myError
            )
        });
        for (local.I = 0;local.I < 3; local.I++) { // Try a bunch of times.
            if (Variables.Return) break; // Gets set in mySuccess and myError
            SpinLock(250);
        }
        return Variables.result;
    }

    var SpinLock = function(milliseconds) {
        var local = {};
        local.StartTime = Date.now();
        do  {
        } while (Date.now() < local.StartTime + milliseconds);
    }

    function WebSqlError(tx,result) {
        if (dom.msg.text()) {
            dom.msg.append('<br>');
        }
        dom.msg.append(result.message);
    }

}(jQuery, window);
Community
  • 1
  • 1
Phillip Senn
  • 46,771
  • 90
  • 257
  • 373

1 Answers1

1

Is there something different about XHR than there is about the executeSql command?

Kind of.

How can jQuery have an async=false argument when it comes to Ajax?

Ajax, or rather XMLHttpRequest, isn't strictly limited to being asynchronous -- though, as the original acronym suggested, it is preferred.

jQuery.ajax()'s async option is tied to the boolean async argument of xhr.open():

void open(
   DOMString method,
   DOMString url,
   optional boolean async,    // <---
   optional DOMString user,
   optional DOMString password
);

The Web SQL Database spec does also define a Synchronous database API. However, it's only available to implementations of the WorkerUtils interface, defined primarily for Web Workers:

window.dbo = openDatabaseSync('POC','1.0','Proof-Of-Concept', 1024*1024);

var results;
window.dbo.transaction(function (trans) {
    results = trans.executeSql('...');
});

If the environment running the script hasn't implemented this interface, then you're stuck with the asynchronous API and returning the result will not be feasible. You can't force blocking/waiting of asynchronous tasks for the reason you suspected:

Maybe my spinning isn't giving the callback chance to come back (See code below).

Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • I wonder if instead of doing an executeSQL, I did an ajax async=false to a page that did an executeSQL, if that would make my transaction synchronous. – Phillip Senn Mar 12 '13 at 16:45