Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting synchronous behavior in javascript?

While developing a mobile PhoneGap app I had an interesting problem. I needed to query about 10 items of data from the database (through PhoneGaps SQLite API)... Like many javascript API's, this one was asynchronous. When you made your query, you would pass in a "success" handler.

Now, my preference in this case would have been a synchronous query method that returned only when complete. Then I could have written straight line code that queried each of the 10 items 1 after another.

Because of the asynchronous nature of PhoneGap (really, I see this all over JS however) I was forced to write a beast that looked like this:

db.query( "SELECT...", success() {
    db.query( "SELECT...", success() {
        db.query( "SELECT...", success() {
            db.query( "SELECT...", success() {
                db.query( "SELECT...", success() {
                }
            }
        }
    }
}

And this is only half as deep as I had to go (and greatly simplified...)... When, had I been using SQLite in C, I could have simply done something like:

db.query( "SELECT...", resultA );
db.query( "SELECT...", resultB );
db.query( "SELECT...", resultC );
db.query( "SELECT...", resultD );
db.query( "SELECT...", resultE );

It seems to me that the success handler approach is great when you only have to go 1 or 2 levels deep... But, completely falls apart when you need more than that...

Is their a library, or feature of a library somewhere that makes this easier?

like image 998
dicroce Avatar asked Dec 19 '11 18:12

dicroce


People also ask

How do I get synchronization in JavaScript?

Synchronous JavaScript: As the name suggests synchronous means to be in a sequence, i.e. every statement of the code gets executed one by one. So, basically a statement has to wait for the earlier statement to get executed. Let us understand this with the help of an example.

Does JavaScript execute synchronously?

Spoiler: at its base, JavaScript is a synchronous, blocking, single-threaded language. That just means that only one operation can be in progress at a time. That's not the entire story, though!

How do you make a function of synchronous in JavaScript?

function init(initData) { return function(param1) { // Return a promise here and the resulting rpc client will be synchronous return Promise.

What is synchronous programming in JavaScript?

Synchronous code runs in sequence. This means that each operation must wait for the previous one to complete before executing. console.


4 Answers

This is a problem that is so prevalent in the community that many patterns and libraries have arisen to combat it.

My favorite is promises. I gave a presentation on promises as a solution to the async problem at a few events; you can check out my slides on SlideShare: Callbacks, Promises, and Coroutines (oh my!): The Evolution of Asynchronicity in JavaScript. It also explains why asynchronicity is necessary---in short, because JavaScript is single-threaded.

For the particular example you give, check out slide 53 and thereabouts. In brief, assuming db.query returned a promise, it would look like:

db.query("SELECT...")
  .then(function (a) {
    return db.query("SELECT..." + a);
  })
  .then(function (b) {
    return db.query("SELECT..." + b);
  })
  .then(function (c) {
    return db.query("SELECT..." + c);
  })
  .then(function (d) {
    return db.query("SELECT..." + d);
  })
  .then(function (e) {
    return db.query("SELECT..." + e);
  });

Of course it becomes a lot nicer if you don't need to use the results of one query for the next:

Q.all([
  db.query("SELECT..."),
  db.query("SELECT..."),
  db.query("SELECT..."),
  db.query("SELECT..."),
  db.query("SELECT...")
]).spread(function (a, b, c, d, e) {
  // ...
});
like image 166
Domenic Avatar answered Oct 26 '22 13:10

Domenic


One basic simplification would be to put the queries in a list and have the same success handler simply call the next query in the list. You would need to hold a pointer to the currently executing query, but it would more cleanly (at least from how the code looks) give you synchronous behavior.

This would work for any closure because you can just set the list values to a bunch of chunks of code, and then execute all of it in order.

like image 27
cdeszaq Avatar answered Oct 26 '22 15:10

cdeszaq


If it's just the nesting that's bothering you, simply chain the methods by name:

function success1() {
    // do stuff to handle success
    db.query("SELECT...", success2);
}

function success2() {
    db.query("SELECT...", success3);
}

function success3() {
    db.query("SELECT...", success4);
}

function success4() {
    // do something
}

db.query("SELECT...", success1);

This won't work if any of those inner success handlers needs access to something that was defined in its lexical scope, but that may not be the case (and even if it is, you could still pass those values as arguments to the next function in the chain).

like image 41
Wayne Avatar answered Oct 26 '22 15:10

Wayne


There is a Open Source Framework know as Siminov Hybrid, it provides ORM for both Native (Java) and Web (JavaScript). By using this you can make all database operations synchronous, because this framework use communication channel provided by Android which is Synchronous.

It is very easy to integrate PhoneGap with this framework. Using this you can work with both Native ORM and Web ORM at same time.

http://siminov.github.io/android-hybrid

like image 37
Pranav Avatar answered Oct 26 '22 13:10

Pranav