Think JavaScript Is Async by Nature? You’ve Been Misled

VANSH KANSALVANSH KANSAL
4 min read

Javascript is by default a synchronous and single threaded language, Yes you heard that right . Now you are must be thinking, One task at a time? Seriously? Yet we use it to build complex, responsive apps every day. How?

It’s all thanks to the event loop — the unsung hero of async JavaScript.


Blocking vs Non-Blocking: The Real Tradeoff

Imagine this: You’re reading a file in Node.js using synchronous code. The program literally pauses until the file is read. Nothing else moves. That’s blocking — and it’s brutal for performance.

Now switch to non-blocking. You use an async method like fs.readFile. The code doesn’t wait. It hands the task off, moves on, and later runs a callback when the file is ready.

Sounds perfect, right? But here’s the catch:

Let’s say you’re building a signup flow. The user submits a form, and you save the data to your database asynchronously. If you send a “Signup successful” message before the DB confirms the save, and the DB fails… you just lied to your user.

So no, it’s not about blocking vs non-blocking being better. It’s about using the right one based on USECASE.


The Event Loop, Simply Explained

Here’s how JavaScript handles all of this magic under the hood:

  • Your code runs line by line in the call stack.

  • When it hits async stuff like setTimeout or fetch, those get sent to the browser’s Web APIs.

  • The browser handles them, and once they’re done, they register callbacks.

  • Those callbacks are placed into:

    • The microtask queue (for promises)

    • Or the macrotask queue (for timeouts, intervals, etc.)

  • The event loop waits until the call stack is empty, then:

    • First runs all microtasks.

    • Then picks one macrotask and puts it on the stack.

And repeat.

That’s how async code doesn’t block the main thread — and how JS stays fast.

setTimeout & setInterval — The Async Duo

If you're working with JavaScript, you’ve definitely seen setTimeout and setInterval — they’re often your first touchpoint with async behavior.

What is setTimeout?

setTimeout lets you run a function after a delay.

setTimeout(() => {
  console.log("Runs after 2 seconds");
}, 2000);

Here, the callback runs after at least 2000 milliseconds. It's useful when you want something to happen later, but not immediately.

Why it's used:

  • Delay UI updates (e.g., show toast, hide tooltip)

  • Simulate waiting (e.g., loading spinners)

  • Add timing to animations

⚠️ Common Pitfalls:

  • The delay isn't exact — it's a minimum wait, not a promise.

  • setTimeout(..., 0) doesn’t run instantly. It still waits for the call stack to clear.

  • Nesting setTimeouts can lead to messy code (callback hell).

Real-world use:

  • Show “copied to clipboard” message briefly

  • Trigger exit popups after a few seconds on a site

  • Debounce user actions like typing (though setTimeout is a building block here)


What is setInterval?

setInterval runs a function repeatedly at a fixed interval.

setInterval(() => {
  console.log("Runs every 1 second");
}, 1000);

It keeps firing every 1000ms unless you stop it using clearInterval.

Why it's used:

  • Create live timers or clocks

  • Poll for changes regularly (e.g., checking if a user is still online)

  • Loop visual effects (like blinking cursors)

⚠️ Common Pitfalls:

  • If your function takes longer than the interval, calls can overlap.

  • Always use clearInterval when it’s no longer needed — or it’ll keep running forever.

  • Not accurate enough for real-time systems (e.g., stopwatches, sync timers)

const id = setInterval(() => {
  console.log("Ping!");
}, 2000);

// Later, stop it
clearInterval(id);

Real-world use:

  • Countdown timer on quizzes

  • Auto-refresh dashboard data

  • Animating progress bars or loading dots

So... Should You Block or Not?

Blocking is fine if you must be 100% sure something is done (e.g., saving to DB before responding to the user).

Non-blocking is better for speed and responsiveness (e.g., loading animations, API calls, user input).

The best devs don’t blindly pick one. They understand when to use each.


Final Thoughts

JavaScript runs one thing at a time — but it’s smart enough to delegate long tasks, and come back to them later. That’s the event loop doing its thing behind the scenes.

If you’re just getting started with async JS, master this first before jumping into async/await, promises, and complex APIs. Once you understand how the event loop works, all of that will make a lot more sense.

1
Subscribe to my newsletter

Read articles from VANSH KANSAL directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

VANSH KANSAL
VANSH KANSAL