SyncScript - Non-Blocking Synchronous JS

Explore SyncScript from the GitHub repository here: https://github.com/irrelon/SyncScript

What is Synchronous Code?

When coding in JavaScript it is very common to see code with callbacks. This allows a process to go off, do something lengthy or time consuming and then callback when complete.

doSomethingLengthy(function (a) {
    console.log(a);
});

Synchronous code by comparison flows naturally from one line to the next without any callbacks. It looks like this:

var a = doSomethingLengthy();
console.log(a);

The sync version of the code has a problem though... it will block execution until doSomethingLengthy() is complete. In a browser this will mean the UI locks up and the user is left with a poor experience.

Callback-based code does not block execution but your code is less readable by another human. If your app is slightly more complex you can have callbacks inside callbacks inside more callbacks.

SyncScript Solves This

SyncScript is JavaScript but adds another keyword that allows you to write synchronous code that executes like callback-based code. SyncScript works in all JavaScript compatible browsers and environments and is 100% JavaScript compatible, requires no extra libraries or downloads and does not need a separate runtime.

All libraries, all plugins and all existing code works without issue with SyncScript.

SyncScript code looks like this:

var a = sync(doSomethingLengthy());
console.log(a);

Passing Multiple Arguments

Let's say we modify doSomethingLengthy() to require some arguments... now the defintion of doSomethingLengthy() is:

var doSomethingLengthy = function (url, flags, callback) {
    // Do some lengthy stuff

    // Lengthy stuff done, callback
    callback('moo');
};

SyncScript will work with this too:

var a = sync(doSomethingLengthy(
    'http://www.irrelon.com', { flag1: true }
));

When this call is done the value passed in the callback is assigned to 'a' so it now equals 'moo'.

Callback With Multiple Values

The above example is great if you only callback with a single value but what about passing back multiple values? That's pretty simple too, just declare multiple variables in the order they are passed back, before the call to sync(). Here is a more likely example:

var err, data = sync(doSomethingLengthy(
    'http://www.irrelon.com', { flag1: true }
));

Setting Callback Scope

You can section areas of code into distinct async calls that will execute in parallel by wrapping them in curly braces. Take the following code for example. The second call to addSync waits for the first to finish:

var err, myVal = sync(addAsync(1, 2, 3, 4));  
console.log(myVal);

var err, myVal = sync(addAsync(1, 2, 3, 4));  
console.log(myVal);  

What if you want both async calls to execute at the same time? You can achieve this by wrapping each call

and it's dependant code in braces:

{
    var err, myVal = sync(addAsync(1, 2, 3, 4));
    console.log(myVal);
}

{
    var err, myVal = sync(addAsync(1, 2, 3, 4));
    console.log(myVal);
}

Now both calls will execute and return in whichever order they complete in.

How SyncScript Works

SyncScript transpiles to an AST after which the tree is analysed, sync calls are identified and then the AST is modified to produce callback-based code where the sync calls are. After modification of the AST it is taken and re-compiled back into JavaScript.

Further Reading

You can read more about SyncScript and the future development roadmap, download and see usage instructions at https://github.com/irrelon/SyncScript