views:

1901

answers:

4

I'm working with a JavaScript API where most of the functions are asynchronous. The API is the WebKit JavaScript Database API which is a binding to a subset of functionality to manipulate SQLite3 databases. I understand the design decision to make things async as to not block and provide a responsive user interface. In my situation I know that my usage of the async API calls will execute fast. Since this is the case I'd like to provide my developers a cleaner and easier to use wrapper API that forces synchronous calls.

Here's the async call

db.executeSql(sqlStatement, function(result) {
  // do something with result
});

And here's what I'd like to be able to do

var result = dbWrapper.executeSql(sqlStatement);
// do something with result

Is there a design pattern/way to do this? A written or linked to code example is preferred. The target platform/broswer is Mobile Safari on the iPhone.

Thank you

+1  A: 

if you are using jQuery Ajax : $.ajax()

you can set the attribute of asynch to false , and then you will have a synch ajax request to the server.

Moran
I did look at he way jQuery implements it's $.ajax() function with the use of an async boolean, but it turns out it just passes the async param through to the XMLHttpRequest.open function which is implemented in "native" code (not js) and therefore can force the synchronous behavior.
methym
+1  A: 

We are using GWT RPC which also has an async API. The solution that we are currently using to make several async calls in serial is call chaining:

callA(function(resultA) {
    callB(resultA, function(resultB) {
        callC(); //etc.
    });
});

This nested approach achieves what you want but it is verbose and hard to read for newcomers. One of the approaches that we have investigated is adding the calls that we need to make to a stack and executing them in order:

callStack = [
    callA(),
    callB(),
    callC()
];

callStack.execute();

Then the callstack would manage:

  1. Invoking the calls in serial (i.e. the wiring in the first example)
  2. Passing the result from one call forward to the next.

However, because Java doesn't have function references, each call on the call stack would require an anonymous class so we stopped short of such a solution. However, you may have more success in javascript.

Good luck!

johnstok
+2  A: 

Sorry, JavaScript does not provide the language primitives (eg. threads or coroutines) to make asynchronous things act synchronously or vice-versa.

You generally* get one thread of execution only, so you can't get a callback from a timer or XMLHttpRequest readystatechange until the stack of calls leading to the creation of the request has completely unravelled.

So in short, you can't really do it; the approach with nested closures on the WebKit page you linked is the only way I know of to make the code readable in this situation.

*: except in some obscure situations which wouldn't help you and are generally considered bugs

bobince
That makes perfect sense. Thanks for the clear explanation.
methym
+1  A: 

You can try something like:

function synch()
{
    var done = false;
    var returnVal = undefined;

    // asynch takes a callback method
    // that is called when done
    asynch(function(data) {
        returnVal = data;
        done = true;
    });

    while (done == false) {};
    return returnVal;
}

But that may freeze your browser for the duration of the asynch method...

Or take a look at Narrative JavaScript: Narrative JavaScript is a small extension to the JavaScript language that enables blocking capabilities for asynchronous event callbacks. This makes asynchronous code refreshingly readable and comprehensible.

http://neilmix.com/narrativejs/doc/index.html

Mike

Mike Gleason jr Couturier