Back to all posts

JavaScript Runtime and the Event Loop

techjavascriptruntimeasyncevent-loop

This week, i'll break down a core concept you need to understand as a web developer: the JavaScript runtime and event loop.

Knowing how this works is key to understanding how your code executes and, crucially, how it keeps your application responsive during time-consuming operations.

What is a Runtime, Anyway?

A JavaScript runtime is the environment that gives your code everything it needs to actually run. It’s made up of two key parts that work together:

  1. The JavaScript Engine: This is the core. It parses, compiles, and executes your code. The most common engine is Google's V8, which is what you'll find in Chrome and Node.js.
  2. A set of APIs: The JavaScript language itself is pretty limited. To make it useful, the runtime gives you a bunch of APIs to grant your code extra powers.
    • In a browser, the runtime provides Web APIs that let your code interact with the outside world: you can make network requests (fetch), manage timers (setTimeout), or directly modify the page's HTML and CSS (document object).
    • In a server environment like Node.js, you get different APIs for server-side work, like an fs module to handle files or an http module to build a server.

So, the runtime is simply the JS Engine + the APIs your environment provides.

The Event Loop: JavaScript's Secret Weapon

JavaScript is a single-threaded language. It has one call stack and can only do one thing at a time. This sounds like a big problem—a slow network request would block the entire application, making it totally unresponsive.

This is solved by the event loop. It’s a clever mechanism that lets JavaScript perform non-blocking operations, keeping your app running smoothly.

Let's look at a classic example:

console.log("Start");

setTimeout(() => {
  console.log("Callback executed");
}, 2000);

console.log("End");

You don't see StartCallback executedEnd. Instead, you see:

Start
End
Callback executed

This happens because of the event loop. Here’s a play-by-play:

  1. console.log("Start") is pushed onto the call stack, runs, and is popped off. "Start" appears in the console.

  2. setTimeout is pushed onto the stack. The runtime recognizes this isn't a core JavaScript command—it's a Web API provided by the browser. Because the single JavaScript thread can't just pause for 2 seconds (it would freeze the page), it hands the callback function () => { console.log("Callback executed"); } and the 2000ms delay over to the browser's native timer to manage. The setTimeout call is then popped from the stack, freeing up the JS thread to continue its work.

  3. The stack is now free, so console.log("End") is pushed on, runs, and is popped off. "End" appears in the console.

  4. Meanwhile, the browser's timer has been counting down. After 2000ms, it decides the task is done and moves the callback function into the Callback Queue, where it waits patiently.

  5. The Event Loop has one job: constantly check if the call stack is empty. When it sees the stack is empty and there's a task in the queue, it takes that task—our callback—and pushes it onto the stack.

  6. The callback function finally runs, and "Callback executed" appears in the console. The function is popped off, and the program is complete.

That’s it. The runtime uses the event loop to offload tasks, keeping the main thread free and your application responsive. Understanding this process is essential for writing code that works the way you expect it to.

sam

Did you find this helpful? Consider supporting my work!

Buy me a coffee