# The JavaScript Call Stack & Event Loop Simplified

One of the concepts that most beginners skip when learning JavaScript is how the JavaScript engine runs code on a single thread, and how browsers handle asynchronous tasks. By understanding the Call Stack and Event Loop, you'll learn how tasks are handled by the JavaScript engine, and hence, start writing non-blocking code.

Now, why should you care? Here are three reasons:

1. You get to understand how JavaScript works under the hood.
    
2. It helps in debugging code.
    
3. Based on my research, questions on the Event Loop and the Call Stack come up in interviews.
    

## What are Stacks and Queues?

We'll be using two important terms in this article: *stack* and *queue*; so, it's necessary that I throw some light on them before the action starts.

A Stack and a Queue are data structures that are supported in most, if not all, programming languages. If you already know what they are feel free to skip this section.

### A Stack

*In computer science, a stack is an abstract data type that serves as a collection of elements, with two main principal operations: push, which adds an element to the collection, and. pop, which removes the most recently added element that was not yet removed.* - [Wikipedia](https://bit.ly/3ndnX6S).

![A Stack](https://www.tutorialspoint.com/data_structures_algorithms/images/stack_representation.jpg align="left")

Take note of the text **Last in - First out** in the presentation above. Stacks use the *Last In, First Out* principle in managing a list (or array) of objects (elements), where the last item **pushed** onto the list is the first to be **popped** off. Makes sense?

A common example of a stack is a pile of books:

![A stack of books](https://i.ibb.co/NSMGzCL/stack-of-books.jpg align="left")

In order to add a new book to the pile of books, you put it on top, making it the last book; but in order to take the first one, Literature, you'd have to take off the last ones: Maths, History, Science.

So, the last item in the stack is the first to go out of it. That's the main idea behind the *stack* data structure.

### A Queue

*In programming, a queue is a data structure in which elements are removed in the same order they were entered. This is often referred to as FIFO (first in, first out).* - [Webopedia](https://www.webopedia.com/TERM/Q/queue.html)

Unlike stacks, a queue uses the *First In, First Out (FIFO)* principle when managing lists. In this case, the element or object which is first added to a list, is the first to go off the list.

A real-life example is a queue of people looking to meet the doctor at a hospital. The person who comes first sees the doctor first, right?

Queues have the idea of *first come, first serve*.

Since this isn't a data structures article, let's get to why we're here.

# The JavaScript Call Stack

*In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program* - [Wikipedia](https://en.wikipedia.org/wiki/Call_stack).

Here, "active subroutines" simply means "active functions" or "invoked (running) functions".

In JavaScript, the **call stack** is a single-threaded stack of function *invocations* in an active JavaScript program.

The call stack is basically a list of functions which have been invoked but aren't done running. The fact that it is single-threaded means only one thing is happening at a time.

Whenever we call a function (e.g. `funcA`), it gets pushed onto the stack as a **stack frame**. A stack frame is a memory location on the call stack.

So, if this particular function depends on another function (e.g. `funcB`), as in it invokes `funcB` in its block, then `funcB` gets pushed onto the stack too, right on top of the function which invoked it; in this case `funcA`.

```javascript
// definition for funcB
function funcB() {
  return "End of B";
}

// definition for funcA
function funcA() {
  // funcB is called inside funcA
  let str = funcB();
}

// now, funcA is called
funcA();
```

Now, here's a visual representation of how the JavaScript engine runs this script:

![Representation of the call stack and the stack frames](https://i.ibb.co/Cs6wj3L/call-stack-eg-1.png align="left")

Okay, let's digest this.

### Explanation

1. First and foremost, where the heck is the `main()` function coming from, and how did it get its own stack frame? When a script (JavaScript code) is executed, the JavaScript engine creates a **Global Execution Context**, which is denoted by `global()` or `main()` function, which gets pushed onto the call stack. Thereby, becoming the first stack frame. We're not responsible for this - the JavaScript engine is.
    
2. In the code we wrote, only `funcA()` was invoked globally (on the last line). This invocation creates a **Function Execution Context** for `funcA()` and pushes it onto the call stack, and it starts being executed.
    
3. In the `funcA()` function, `funcB()` is invoked - where its returned string is stored in the variable `str`. At this point, a **Function Execution Context** is created again for `funcB()` and a stack frame is created for it and gets pushed onto the call stack.
    
4. Inside `funcB()`, every task (or code) is run until the last line (in our case, the `return` statement) which marks the end of the function. On this note, the function exits and is popped off the call stack. Since the call stack is a **stack** data structure, the last item goes out first (Last In, First Out). Therefore, `funcB()` is the first to be popped off the call stack.
    
5. When `funcB()` finishes executing, its returned value is obtained by `funcA()` which is stored in the `str` variable. And since the variable initialisation is the last line of `funcA()` it marks the end of the function, and hence causes the stack frame of `funcA()` to be popped off the call stack.
    
6. Now, since there are no more functions to be executed by the JavaScript engine, the Global Execution Context exits and `main()` or `global()` is popped off the call stack too, leaving it empty.
    

![Explaining the call stack](https://i.ibb.co/RH7Q7tV/call-stack-explain.png align="left")

If the image above isn't big enough just open it in a new tab and zoom in.

# Stack Overflow

Before you get overly excited, this section isn't about the forum [stackoverflow.com](www.stackoverflow.com) 😅.

There's a maximum number of stack frames that can occupy the call stack.

If this limit is exceeded, a stack overflow occurs. In other words, the JavaScript engine throws a `RangeError` exception (in Chrome), or `InternalError` exception (in Firefox).

But how could this ever happen?

A common way a stack overflow could occur is when a recursive function is executed without an exit condition.

A recursive function is any function which invokes itself in its definition block.

When such a function is invoked and no condition is provided for it to stop infinitely calling itself, the stack size limit is exceeded and a stack overflow occurs.

Here's an example of a recursive function which has no exit condition:

```javascript
function example() {
  // calling the same function inside its block
  example();
}

// now call the function
example();
```

Copy the code above and run it. Check the developer console and you'll see an error which looks like this (Chrome):

![Stack overflow error](https://i.ibb.co/Ky4WBkV/stack-overflow.png align="left")

Learn more about recursive functions [here](https://www.javascripttutorial.net/javascript-recursive-function/).

---

I mentioned earlier that JavaScript is single-threaded, and that it runs one task at a time.

So, how does it handle asynchronous tasks?

## Asynchronous Tasks

JavaScript code is run from top to bottom; tasks that are written first are executed first. However, this is different from asynchronous tasks.

Basically, asynchronous tasks are those that take some time before they complete. An example is fetching data from a remote server. Another instance is writing `setTimeout()` to invoke a function after several milliseconds.

Let's examine this code:

```javascript
console.log("start");

// print "middle" after 1 second
setTimeout(() => {
  console.log("middle");
}, 1000);

console.log("end");
```

Result:

```plaintext
start
end
middle
```

As you'd expect, the `setTimeout()` fired its callback after a second, but then the browser skipped it and executed the `console.log()` at the end before coming to execute the callback in the `setTimeout()`.

How does that happen under the hood when we know JavaScript has one call stack and is single-threaded?

First of all, the first `console.log()` is pushed onto the call stack (after the global execution context, of course).

![example](https://i.ibb.co/zVLLyky/e-loop-eg1.png align="left")

And after it logs to the console, its stack frame is popped off the call stack.

![example](https://i.ibb.co/RSkPPY5/e-loop-eg1b.png align="left")

Then, the `setTimeout()` is pushed onto the call stack.

![example](https://i.ibb.co/HFPWPGd/e-loop-eg2.png align="left")

Browsers come with their APIs (Application Programming Interfaces), such as `setTimeout`, the DOM, `XMLHttpRequest`, etc. These APIs aren't provided by the JavaScript engine and hence, it doesn't know how it can execute such code. Therefore, the engine immediately marks it as complete (without running it), pops it off the call stack, and lets the browser or Web API handle it.

So, our `setTimeout()` is popped off the call stack so the Web API handles it, and then a timer is placed on its callback by the Web API.

![example](https://i.ibb.co/NCbdjt4/e-loop-eg3.png align="left")

At that point, since it has been removed from the call stack, the JavaScript engine continues executing the code, and the last `console.log()` is pushed onto the call stack and executed, whilst the `setTimeout()` callback is being handled by the Web API.

![example](https://i.ibb.co/YPmtKbW/e-loop-eg4.png align="left")

# The Callback Queue

The moment the provided time on the `setTimeout()` expires, in this case, 1 second, the callback is pushed onto the **Callback Queue**.

![example](https://i.ibb.co/xCZyMPD/e-loop-eg5.png align="left")

And obviously, by now, the last `console.log()` had already been executed and popped off the call stack, meaning the script is done running.

![example](https://i.ibb.co/YTzR1MY/e-loop-eg5b.png align="left")

Remember what the *queue* data structure is?

The **Callback Queue** is a first-in-first-out data structure. Meaning, the first function which it takes is the first to go out of it.

Why didn't the Web API push the callback function directly onto the call stack? The reason is that, by the time the timer on the callback expires, the call stack may be busy executing functions.

So, the asynchronous code is enqueued on the Callback Queue, waiting to be pushed onto the call stack by the *event loop*.

# The Event Loop

The *event loop* is an endless loop which has only one goal: push tasks (from the callback queue) onto the call stack when the call stack is done running the script.

The *event loop* keeps checking both the call stack and callback queue; if the call stack is empty, it checks if there are any queued tasks on the callback queue. If there are any, it pushes them onto the call stack.

So, now that the JavaScript engine is done executing code and the call stack is left with no more code or functions to execute, the event loop takes the callback from the callback queue and pushes it onto the call stack to be executed.

![example](https://i.ibb.co/GQbNmPz/e-loop-eg6.png align="left")

The callback is run, and the engine notices it calls `console.log()`. It takes that and runs it too, pushing it onto the stack.

![example](https://i.ibb.co/YtpqMKS/e-loop-eg7.png align="left")

After it logs the string "middle" to the console, it is popped off the call stack.

![example](https://i.ibb.co/Wxcs56b/e-loop-eg7b.png align="left")

Since the callback is done executing, it is popped off the call stack also.

![example](https://i.ibb.co/MBrP1Tq/e-loop-eg7c.png align="left")

That's how we got this result:

```plaintext
start
end
middle
```

---

Rewrite the `setTimeout()` function with a time of zero milliseconds, and run the code.

```javascript
setTimeout(() => {
  console.log("middle");
}, 0);
```

Zero milliseconds means no delay, right? We'd expect to see the string "middle" before "end" but no, the same result is yielded:

```plaintext
start
end
middle
```

This is because the `setTimeout()` is a Web API. Therefore, before it's executed, it has to be processed by the browser, and then enqueued in the callback queue, where it waits until the call stack is no longer executing functions, and then it's pushed onto the call stack and executed.

---

This marks the end of another article. If you're still scratching your head I suggest that you take some time off, bookmark the page, and come back later to read again.

If you like the article, don't forget to react, share, and follow me or subscribe to my newsletter so you don't miss my future articles.

Thank you!
