Some Observations On Asynchronous Programming In Client Side JavaScript

Programming operations asynchronously in client-side JavaScript can make life a lot easier. Lately, I found myself wondering what async truly means in this case, did some investigations and figured it would be worth mentioning.

My main focus is with the use of the setTimeout (and setInterval) methods in the traditional browser based JavaScript environment (you know, with that pesky DOM api and what not), though Web Workers are ideal for truly concurrent programming.

A basic example:

window.setTimeout(function () {
console
.log("hello world!");
}, 1);

This causes the interpreter (V8 as my main test) to schedule the function to call in 1ms. Taking that into account, what exactly is setTimeout doing in this case and how does it vary. Let us consider a more elaborate example:

function test_one() {
console
.log("settimeout call!");
}

function test_two(){
window
.setTimeout(test_one, 1);
for (var i = 0; i < 10000000; i++){ }
console
.log("inner loop done!");
}

(function (){
test_two
();
for (var i = 0; i < 100000000; i++) { }
console
.log("loop done!");
}());

==> inner loop done!
==> loop done!
==> undefined
==> settimeout call!

We can see that regardless of where the call is all window.setTimeout calls are blocked until the call stack recurses back up to the global name space. This is something to keep in mind when programming operations that are not concurrently executed.

You also may be wondering why all the setTimeout calls are scheduled to execute in 1ms instead of 0ms. We do this because (as pointed out by Ates in the comments below) not all JavaScript engines execute a setTimeout call for 0ms in the same way, and would instead call the function immediately.

With this in mind, consider another example where you create a publish subscribe event class (an example) and use it to asynchronously trigger events in a function like this:

function () {
Event.trigger("some_event");
Event.trigger("another_event");
}

If called asynchronously the "some_event" triggers will only begin execution (in chronological order of registration) when the second method (that triggers "another_event") finishes execution and registration of it's own timeout calls, which would follow execution in the same manner.

Too see this, an example:

function test_one_callback() {
console
.log("test_one_callback done!");
}

function test_two_callback() {
console
.log("test_two_callback done!");
}

function test_two(){
for (var i = 0; i < 100000000; i++){ }
window
.setTimeout(test_two_callback, 1);
console
.log("test_two done!");
}

function test_one(){
window
.setTimeout(test_one_callback, 1);
console
.log("test_one done!");
}

(function (){
test_one
();
test_two
();
for (var i = 0; i < 10000000; i++) {}
console
.log("loop done!");
}());

==> test_one done!
==> test_two done!
==> loop done!
==> undefined
==> test_one_callback done!
==> test_two_callback done!

A small test but a good illustration of async operation sheduling in client side JS. If anyone has any additions, corrections or comments they are of course more than welcome.

Now, back to some code.

About these ads

2 Responses

  1. I always use a timeout of 1 ms to make things asynchronous. A 0 ms delay can get short-circuited to an immediate function call (like you mentioned) in some engines. It should also be kept in mind that an engine can have a minimum timer resolution like 10 ms. So, essentially, the only surefire way to achieve asynchronicity is to accept a >=1 ms delay. But, in the browser environment, since “snappiness” is usually bottlenecked by the user’s slowness, a >= 1 ms delay won’t make any difference.

    • Thanks for the comment Ates. That was something I did not consider. :-)

      I updated the post to reflect that as well.

      Cheers,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: