Behind The Scenes Of addEventListener

The event listener is an asynchronous event and goes to the web API and not directly to the JS call stack.  When an event that is attached to an addEventListener fires, the event handler addEventListener causes the web API in the browser to set-up a macrotask event queue in the event loop. This event macrotask queue in the event loop will wait for the JS call stack to completely clear and eventually get executed in the call stack. Although events look quite similar to callbacks, the difference lies in the fact that callback functions are called when an asynchronous function returns its result, whereas event handling works on the observer pattern.


The event listener is the event you create to listen for any incoming events. The event handler is the callback that will be triggered once the event listener hears the event.


When the code moves from the event loop back to the call stack, it opens a local execution context and the code is executed until it returns something out of the function. This event object stores properties such as target which holds where the nodes of the event originated. The event object can be accessed through a function that usually has the parameters of something of something like e, evt, or event and evt.target.style.backgroundColor can set properties to the event object. The event object can use forEach and length but not the other array methods like map, filter and reduce because it holds data in a node list which is an array-like function but not an array. Array.from would have to be used to convert a node-list to an array if you need to use array methods like map, filter and reduce.


When you want your event listener to listen for some precise attachment, you may want to use evt.currentTarget instead of evt.target. For example, if you put a span tag in a button, the user may click the span tag by accident instead of the button. Now with event bubbling, clicking the span tag also clicks the button and also clicks the parent div tag and also clicks the grandparent body tag and so on and so forth. In target.addEventListener(event, callback, useCapture), the third useCapture parameter is an optional boolean value that specifies whether the event should be executed in the capturing or bubbling phase. In the case of nested HTML element, this is where you can define priorities such as which event gets executed first. By default, it’s set to false which means the innermost HTML event handler is executed first. To stop event bubbling, you can use the stopPropagation method to prevent event handlers from bubbling up the event bubbler. The preventDefault prevents the browser’s defaults from handling the events but should be used with extreme caution.


Node.js is an event-driven language and this makes it’s performance faster to similar technologies. Since Node.js is built on Javascript which inherently single-threaded, for it to create concurrency and not be slow like traditional servers,  it uses events to listen for requests. As a comparison, Apache usually a multi-threaded approach which means it must expend resources for every request that it receives. Multi-threaded approaches lag in performance because all the requests have to come back before serving the page. Because Node.js gets processed faster, the client has a better user experience.


Node.js reads your code and first looks for subscribe events, such as requestlistenconnection, or close. And patiently like a fisherman, it sits in the event loop and listens for these events continuously inside a single thread. It always processes request events and next close events. Once someone triggers an event, for example, the request (req) event, the callback of this event gets sent into an event queue. It’s really just the macrotask queue in the event loop and the same thing as what we call the callback queue.


A timer specifies the threshold after which a provided callback may be executed rather defining an exact promised time that the coder requested in setTimeout. Timers callbacks will run as early as they can be scheduled after the specified amount of time has passed; however, delays may occur due to operating system scheduling or other scheduled callbacks before them in the task queue.


This is the end of our behind the scenes tour of addEventListener. Hopefully, understanding what’s going on a deeper level will help you to write better code.