The Event Loop

Code Synchronicity

In the previous section on the Call Stack, we used the terms:

  • run-to-completion
  • single-threaded

Another term for this issynchronous. By definition, "synchronous" means:

existing or occurring at the same time

All of the code we've been looking at runs in order, at the same time. Functions are added to the call stack, and then removed from the call stack when they've completed. However, there is some code that is_not_synchronous - meaning that the code is written just like any other code, but it is executed at some later point in time. Does this sound familiar at all? You've just been working with it:

const links = document.querySelectorAll('input');
const thirdField = links[2];

thirdField.addEventListener('keypress', function handleKeyPresses(event) {
    console.log('a key was pressed');
});

...event listeners!_Most_of this code is synchronous like you're used to. But the event listener's functionhandleKeyPressesis_not_invoked immediately, it's invoked at some later point in time.

Have you ever wondered about that? Where does the code go? What about the "call stack" that we learned about? Is it hidden in the call stack somewhere?

Let's look at this code snippet:

console.log('howdy');
document.addEventListener('click', function numbers() {
    console.log('123');
});
console.log('ice cream is tasty');

The code will run in this order:

  1. 'howdy' will be logged to the console
  2. 'ice cream is tasty' will be logged to the console

The string'123'will only be logged if there's a click. If the page is never clicked, then this code might not ever run! But where is it? Where did thenumbersfunction holding theconsole.log('123');code go?

Running Code Later

But the same questions exist for this code as it does for the.addEventListener()code:

  • where does the function go to wait?
  • how does the function get run when it needs to?

This happens because of the JavaScript Event Loop!

The JavaScript Event Loop

The simplest explanation of JavaScript's_concurrency model_uses two rules: If some JavaScript is running, let it run until it is finished ("run-to-completion"). If no JavaScript is running, run any pending event handlers.

Since most JavaScript is run in response to an event, this is known as anevent loop: Pick up the next event, run its handler, and repeat.

There are three parts you have to think about around the event loop:

  • the Call Stack
  • Web APIs/the browser
  • an Event Queue

Not all of the code that we write is 100%_JavaScript_code. Some of the code is interacting with the Web APIs (also known as "browser APIs"). There are many more examples, but both.addEventListener()andsetTimeout()are Web APIs.

Let's look back at this code:

console.log('howdy'); // 1
document.addEventListener('click', // 2
  function numbers() {
    console.log('123');
});
console.log('ice cream is tasty'); // 3

First, the browser runs this block of code to completion -- that is, steps 1, 2, and 3. Step 2 passes an event handler (numbers) to the browser for future use: the browser will hold this function until there's a click event.

What happens if someone clicks before this block of code is done? When there is a click event and there is code already running, thenumbersfunction can't just be added directly to the Call Stack because of JavaScript's run-to-completion nature; we can't interrupt any code that might currently be happening. So the function is placed in the Queue. When all of the functions in the Call Stack have finished (also known asidle time), then the Queue is checked to see if anything is waiting. If something is in the Queue, then it's run, creating an entry on the call stack.

IMPORTANT: The key things to remember here are 1) current synchronous code runs to completion, and 2) events are processed when the browser isn't busy. Asynchronous code (such as loading an image) runs outside of this loop and sends an event when it is done.

QUIZ QUESTION

What is the order that theiceCreamfunction goes through if the<footer>is clicked?

const pageFooter = document.querySelector('#page-footer');

pageFooter.addEventListener('click', function iceCream () {
    const footerDetails = document.querySelector('#details');

    footerDetails.textContent = 'Everyone should eat ice cream!';
});

the Queue

the Call Stack

Browser

ORDER

EVENT LOOP LOCATION

First : Browser

Second: the Queue

Third: the Call Stack

SUBMIT (When this code is run, the iceCream function is given to the browser. When the <footer> is clicked, the code moves to the Queue. Then, when the Call Stack is empty, iceCream is moved over to the Call Stack and invoked.)

Recap

This section uncovered how JavaScript works under the hood; We looked at how JavaScript, the DOM, and Web APIs all fit together.

Specifically, we looked at how JavaScript is a single-threaded programming language, which means it can only execute one thing at a time. We looked at how JavaScript keeps track of what functions are running by using the Call Stack. We also looked at how asynchronous code is handled.

Asynchronous code makes use of the JavaScript Event Loop. Any asynchronous code (likesetTimeoutor the function passed to.addEventListener()) is handled by the browser. When this asynchronous code is ready to be executed, it's moved to the queue where it waits until the Call Stack is empty. Whenever the Call Stack is empty, code moves from the Queue over to the Call Stack and gets executed.

Knowing how JavaScript and the Event Loop work can help us write code that is more efficient.

Further Research

results matching ""

    No results matching ""