0

So I have a Javascript Class that wraps and manages access to the WebSQL Database system.

the code for the class can be found: https://jsfiddle.net/dsct89kv/

now to test it I'm using

function(){
    var test = new Database();
    test.open("test");
    test.query("CREATE TABLE `logs` (id INTEGER PRIMARY KEY, value VARCHAR)");
    test.query("SELECT * FROM `logs`"); 
    test.waitForBlockLift(); 
    console.log(test.fetchRows());
  }

if I run all of these line by line one after another in the console it works perfectly but if I run the group it becomes thread locked on test.waitForBlockLift();

so that is defined as

this.isBlocked = function(){ return blocking; };

this.waitForBlockLift = function(){
    var test = this.isBlocked();
    while(test){
        test = this.isBlocked();
    }
    return true;
}

the initial value of blocking = false when a query is called test.query it is set to true and once the transaction has completed and called the callback then set it back to false but for some reason when I call in a single line from the Console e.g test.query("SELECT * FROM logs"); test.waitForBlockLift(); console.log(test.fetchRows()); that does not happen the javascript engine works as I can still use the console. however, I can't access test and the tread appears to lock the whole point was to enable it to wait for the thread to unlock.

I must be doing something wrong but can't work out what

Barkermn01
  • 6,781
  • 33
  • 83

1 Answers1

1

In the main thread of Javascript, this construct:

this.isBlocked = function(){ return blocking; };

while(test){
    test = this.isBlocked();
}

is an infinite loop. That's because the main execution path in Javascript is single threaded. So, while you're looping there in that single thread, nothing else can ever run. Therefore the blocking variable can never be changed, thus your loop runs forever. You can't do a wait loop like this in Javascript.

Instead, you have to use completion callbacks to know when asynchronous operations are done. You don't show any of your actual database code, but all database operations should have callbacks that will tell you when they are done. You will need to use those to know when operations are complete. You pass a callback and it will call you when things are done. This then allows other code to run while you are waiting for the callback function to be called.


Per your comments, in Javascript, you would not do this:

test.query("SELECT * FROM logs");
console.log(test.fetchRows());

Instead, you would use a completion callback to do something like this:

test.query("SELECT * FROM logs", function(result) {
    console.log(test.fetchRows());
});

Or, if you returned a promise from test.query(), you could code it like this:

test.query("SELECT * FROM logs").then(function(result) {
    console.log(test.fetchRows());
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I'm slightly confused I'm using the callback to change the `blocking` is that call back not called on a separate thread to the main I thought that was the points of callbacks. so how in do you convert something async to use thread blocking if I can't use a busy wait on the main thread? – Barkermn01 Mar 18 '16 at 17:06
  • 1
    @MartinBarker - The database code itself probably runs on its own thread, but when it calls a Javascript callback, that goes through the event queue and has to wait until the Javascript thread is free before the Javascript callback will execute. You can read [this post](http://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background/7575649#7575649) to understand a bit more about the event queue. Except for special things like webWorkers, your Javascript code is completely single threaded. If it's executing one place, it can't do anything else. – jfriend00 Mar 18 '16 at 17:11
  • ok so is there a native way to cause thread blocking on main thread until a callback is fired? i'm researching it now but if you know a way would be helpfull, thanks for the link i will have a read :) the problem is if i run `test.query("SELECT * FROM logs"); console.log(test.fetchRows());` without waiting for it i get a a managed exception coz the async thread has not finished – Barkermn01 Mar 18 '16 at 17:12
  • @MartinBarker - No. You cannot write Javascript code that way. You have to structure your code using non-blocking techniques and callbacks. So, code that wants to execute when a particular condition is met, must register a callback for that event and then put the code you want to run IN that callback or call a function from that callback. That's how you handle async operations in Javascript. Javascript has an "evented, non-blocking I/O model" and it does not offer a blocking threaded alternative. – jfriend00 Mar 18 '16 at 17:16
  • Ok thanks well that's slightly annoying you would think they would have enable a method of thread locking by now being that threads has been added to Javascript but we still can't build thread-safe code. – Barkermn01 Mar 18 '16 at 17:21
  • @MartinBarker - The lack of blocking threads is fundamental to how Javascript achieves CPU efficiency and scalability and keeps the programming model from being exposed to race conditions, concurrency bugs and needing mutexes and all that stuff. If you've only known the blocking model, it is a bit of a new way of doing things, but once you grok it, it starts to really make sense as an alternative way. And, learning promises (now standard in ES6) can really help with async programming too. I added a bit more to the end of my answer about using a callback to signal completion of an async event. – jfriend00 Mar 18 '16 at 17:24