The Javascript Event Loop

Hilary Egesa
The Andela Way
Published in
5 min readApr 15, 2020
Photo by Tine Ivanič on Unsplash

Programming or software development, in general, is an interesting domain whose knowledge grows daily at exponential rates. Programming languages and their accompanying frameworks are always evolving and becoming more magical so fast that keeping up might seem cumbersome at times. The good thing is that the fundamentals rarely change. The simplification and speed frameworks and other tools bring to us are very welcome, but once in awhile, you come across a problem that requires you to know what is going on under the hood.

I am not writing this blog to point out a specific need for knowing the workings of a Javascript event loop, cough!! cough!! asynchronous javascript. I am just saying that I find it satisfying to dive a bit deeper once in a while because javascript is single-threaded and you never know when such knowledge might come in handy.

There are blogs written by more experienced Javascript veterans out there about the subject. I have read some of them before but I could not understand fully what was going on until I did the Advanced Node.js course on Pluralsight by Sumer Buna where this was one of the sub-topics therein. I have not tried to advertise anyone or any platform but maybe it could be that I learn better visually. That said, I hope the knowledge I obtained from that course and the content I read on the internet can help fill the gap you might have had while scouring the web for such an explanation.

Javascript is a single-threaded programming language where the execution of functions is done one at a time, unlike C or Java. In C and Java, a function (let's call it funcA) can be stopped when an interruption is triggered by a function (funcB) in another thread. In such a case the state of the funA is saved and control is turned over to funcB. Once the rude funcB has finished executing control is returned to funcA and its own execution continues.

To manage many functions in Javascript’s single threading, the event loop, together with a call stack and a message queue comes in handy. All functions are added to the message queue as messages. The same is the case for events such as clicks within a browser that has a listener. As the name suggests, the message queue is a first in first out data structure that will ensure the oldest event gets handled first and the newest last.

To get a picture of the conceptual models of event loops, call stacks, message queue and maybe even the objects heap, you might have come across a similar diagram to the one below

Representational Concepts: Image courtesy of MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

It is the work of the event loop to pick up a message from the message queue and invoke its corresponding function known as a callback. A function is placed on the call stack for execution in the form of a stack frame. In the case of a click event, the listener function and its contents are put on the call stack. A stack frame contains all of a function’s arguments and variables. If this function calls another function, this function’s frame will be placed on top of its caller on the stack and so on. Once the topmost function’s stack frame has finished executing it gets popped out of the call stack and execution proceeds to the current topmost stack frame. All the while the event loop keeps checking if the stack is empty. When it happens that the call stack is empty, the event loop checks if there are other messages waiting on the queue and begins processing the oldest message on the queue as it had done before.

Arnold’s career stack functions

I will demonstrate these concepts using the above list of functions roughly detailing Arnold Shwarzenneger’s career path in various industries he has been part of. Let us assume during a window.onload event the browser calls becomeAbodyBuilder(24,197). This event will be placed as a message on the message queue. Later on, in the javascript runtime, the event loop will have to process this message by removing the message from the queue and invoking its corresponding function. A call stack frame will be created with the arguments and dateOfbirth variable. becomeAbodyBuilder’s stack frame will be the first item on the stack and therefore the last to be processed.

The visualisation of the stack from this code can be seen in the next diagram. The sequence of diagrams are snapshots of the call stack sequentially from 1 to 6 as referenced by the yellow boxes. The stack 1 shows the frames that were created as a result of calling becomeAbodyBuilder(). Console.log() is the function in the highest stack frame. It gets executed and immediately popped off. Next becomeGovernor() is also popped off and becomeAnActor() continues execution by calling console.log() which is popped off immediately as seen in call stack snapshot 3. This behaviour continues until snapshot 6 where becomeABodyBuilder() also gets popped and we have an empty call stack.

Sometimes later the EventLoop will discover that the call stack is empty and will check to see if we have a message waiting on the message queue. If it finds one then a story similar to the one we have just witnessed will unfold once more.

This single handling of a message ensures it is processed to completion and hence removing some of the problems associated with multi-threading. A good case here is where funcB above might change variables that were being manipulated by funcA causing reliability or accuracy issues.

I will end it there for this part since I did not want to make this blog more complicated with asynchronous javascript that is usually brought about by the use of the setTimout() function and its siblings. My main aim was just to bring out an understanding of how the event loop, call stack and message queue work together to ensure that javascript code executes seamlessly in a single-threaded environment.

--

--