The callback pattern

Previously, we described what asynchronous and synchronous code looks like when you encounter it in your everyday life as a developer. What might be of interest is to know how an operating system looks at such code and how it deals with it. An operating system deals with asynchronous code by thinking of it in terms of the following concepts:

  • Events, these are messages that signals to the operating system that a certain type of action has occurred
  • Event handler, this is the piece of code that should run when an event has occurred
  • Event queue, this is where all events and their event handlers are placed, waiting to be executed

Let's illustrate this flow in the following diagram:

What we can see in the preceding image is how events are being picked from an event queue. Here, the CLICK event is being run when a Dispatcher tells it to and its corresponding event handler is executed. The event handler runs the associated lines of code in the event handler and when that's done, gives control back to the Dispatcher. Thereafter, the cycle begins anew for the next event in the queue. This is what it usually looks like in a single-threaded system, where only one event handler is executed at a time.  There is also such a thing as a multithreaded system. In a multithreaded system, multiple threads exist. This means we might have several event handlers being executed at once. But even though there are multiple threads, there is only one active thread. The system itself is still single-threaded. Confused? Here is the thing: threads in a multithreaded system are cooperative, which means they can be interrupted. This means that the active thread is changed after a unit of work has been carried out. This creates an effect where it seems like everything happens in parallel. Let's illustrate this for clarity:

Here, we can see that a piece of code is divided into different regions. When a certain region has been executed, it gives control to the next Thread, which becomes the new Active thread. Once that thread has executed code through one of its regions, it gives control to the next thread. With the arrival of multiple CPUs, we are able to go from perceived parallelism (described previously) to actual parallel execution. In such a reality, one thread per CPU exists and we therefore have multiple active threads. 

These are the different ways you can execute asynchronous code. We will focus on single-threaded execution, as this is how it is implemented in JavaScript and on the web.