[Developer says] Gazing into the abyss of Javascript asynchrony

Albeit master of none, Javascript is a true jack of all trades. It can wear the hat of object orientation, of functional programming, event driven and even procedural under certain circumstances. The defining feature however is it’s invariably non-blocking scheme.

Let’s start with some terminology. Javascript is said to be asynchronous and non-blocking. The terms “asynchronous” and “non-blocking” are used interchangeably in this context. They mean that a system will never wait for anything. It will instead register an event to be triggered when the otherwise delaying factor finishes. That is in contrast to blocking systems that will pause after attempting to interact with an external resource for in wait for the operation to finish before continuing. There are chiefly two cases where the asynchronous scheme becomes crucial for Javascript.

  • When a task depends on user input. Eg when the “Flash on arduino” button is clicked, the browser starts interacting with the device but we can’t freeze the entire platform in wait for this particular button to be pressed.
  • When a task depends on external IO. Eg send the user’s code to the compiler server but don’t just wait for the response, continue with the rest of the website’s functionality, and when the response arrives begin the flashing process.

Closures

closure

Let’s talk about the task themselves first. A task is nothing more than a block of Javascript code and a set of references to the variables that that block has access to. For example:

var a = "Scheduled", b = "Not scheduled";
setTimeout(function () {
  console.log(a);
}, 10);

console.log(b);

This code schedules a task to be executed in 10ms. That task has access to all variables that are in scope when the function was declared, that is a and b. This task is also called a closure and it is a pretty common pattern in functional languages. The feature that we just described is called lexical scoping which is supported by Javascript, as opposed to dynamic scoping which is found on less functionally oriented languages like python or ruby.

The above code should output:

Not scheduled
Scheduled

And that makes perfect sense, since we schedule the output of the value of a, then we output the value of b and 10ms later the scheduled.

Message queue

back of the queue

Consider now the following example:

var a = "Scheduled", b = "Not scheduled";
setTimeout(function () {
  console.log(a);
}, 0);

console.log(b);

This outputs again:

Not scheduled
Scheduled

That may seem slightly strange. We scheduled the first log to be executed immediately. But the following command is executed first. That is because “immediately” actually means “when you get the time”. Let us examine a demonstrative usecase from Facebook:

  • The user writes a comment for a Facebook post but does not yet click “Post comment”
  • A new comment is received
  • Two likes are received by the server for that post
  • The user clicks “Post comment”
  • The comment is rendered

Javascript maintains a message queue and puts in there any task it needs to accomplish. It always processes the first task and pushes new tasks to the back of the queue. Therefore what actually happens is:

  • The received comment starts to render
  • The likes are received and their rendering is queued
  • The “Post comment” button is clicked and comment posting is queued
  • The comment rendering finishes
  • Each of the likes is rendered
  • The user’s comment gets posted.

Of course this is a rather simplified interpretation of what is going on, and a modern computer will make all the above seem instantaneous.

Part 2