Leaderboard
Javascript Jun 4, 2026
Javascript Promises Async Not Multithreaded Myth

JavaScript Async/Await — Separate Thread or Event Loop?

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Promises Async Not Multithreaded Myth and improve your technical interview readiness.

A TRUE — they use web workers internally
B FALSE — they still run on the main thread, just in a different order
C TRUE — that is why they are faster
D FALSE — only setTimeout uses a separate thread

Detailed Explanation

Why This Question Matters

The question is simple: TRUE or FALSE: Promises and async/await run code in a separate thread.

The answer is FALSE, but if you ask ten developers in a room, at least three will probably tell you it's true. Why? Because async and await *feel* like multi-threading. When you await a database call or a fetch request, your UI doesn't freeze. The app keeps running. Naturally, we assume JavaScript is spinning up a new thread in the background to handle that heavy lifting.

This is one of the most dangerous misconceptions in JS. If you think async/await is multi-threading, you'll eventually write a "background task" that accidentally blocks your entire event loop, and you'll spend hours wondering why your app is lagging despite using async everywhere.

Understanding the Logic

To get why this is false, you have to look at the JavaScript engine. JS is single-threaded. Period. It has one call stack and one memory heap. It can only do one thing at a time.

So, how does it handle "asynchronous" work? Through the Event Loop.

When you use a Promise or an async function, you aren't creating a new thread. Instead, you're telling the engine: *"Hey, start this operation (like a network request), and let me know when it's finished. In the meantime, I'm going to keep executing other code."*

Here is the internal flow:
1. You call an async function.
2. The code runs synchronously until it hits an await.
3. The await keyword literally pauses the execution of *that specific function*.
4. The function is "shelved," and the engine jumps back to the main call stack to keep running other scripts.
5. Once the awaited Promise resolves, the result is pushed into the Microtask Queue.
6. The Event Loop checks if the call stack is empty. If it is, it grabs the resolved Promise from the queue and resumes your function.

Nothing ever left the main thread. The "waiting" happens in the browser's Web APIs (like the network stack) or Node.js's C++ internals, not in a JS thread.

Finding the Correct Answer

The answer is FALSE because async/await is just syntactic sugar for Promises. And Promises are just a way to manage the order of execution in the Event Loop.

If you write a Promise that contains a massive for loop calculating prime numbers up to a billion, your browser will freeze.

// This will FREEZE your UI/Server
async function heavyTask() {
  console.log("Starting...");
  
  // This is NOT on a separate thread. 
  // It blocks the entire main thread.
  let sum = 0;
  for (let i = 0; i < 1e9; i++) {
    sum += i;
  }
  
  console.log("Finished!");
}

heavyTask();
console.log("I will never run until the loop is done!");

In the example above, even though the function is marked async, the loop is synchronous CPU work. Since there's no actual I/O (like a file read or network call) to hand off to the system, the single thread is occupied. If it were truly multi-threaded, the "I will never run" log would appear immediately.

Common Mistakes Developers Make

The biggest mistake is confusing Asynchronous I/O with Parallelism.

- Asynchronous I/O: "I've asked the database for data. I'll let you know when it arrives." (This is what Promises do).
- Parallelism: "I have four CPU cores; I will run these four different calculations at the exact same time." (This is what Worker Threads do).

Developers often wrap a heavy computation in a Promise, thinking it magically becomes non-blocking:

// WRONG: This still blocks the main thread
new Promise((resolve) => {
  for (let i = 0; i < 1e9; i++) { /* heavy work */ }
  resolve();
});

A Promise is not a thread. It is a placeholder for a future value. If the code inside the Promise is CPU-intensive, you are still blocking the event loop.

Real-World Usage

In production, this distinction is critical for performance tuning.

If you're building a Node.js API and you need to process a massive JSON file or encrypt a password using bcrypt, doing it inside an async function isn't enough. If you do that on the main thread, every other user hitting your API will experience a timeout because the event loop is stuck processing that one heavy request.

To actually achieve multi-threading in JavaScript, you have to use:
- Web Workers (in the browser)
- Worker Threads (in Node.js)

These actually spawn a separate OS thread with its own V8 instance and memory space. They communicate with the main thread via message passing (postMessage), which is the only way to truly run JS code in parallel.

Key Takeaways

- JS is single-threaded. async/await does not change that.
- Async $\neq$ Parallel. Asynchrony is about *waiting* without blocking; parallelism is about *doing* multiple things at once.
- The Event Loop manages the execution order via the Microtask Queue.
- CPU-heavy tasks will block your app regardless of whether you use async or Promises.
- Use Worker Threads if you actually need to move heavy computation off the main thread.

Why this matters

Understanding Promises Async Not Multithreaded Myth is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.

📝
Reviewed by CodeShot Editorial
Every challenge is code-reviewed by senior developers to ensure accuracy and real-world relevance. Learn more.

Ready for your shot?

Join thousands of developers solving one logic puzzle every morning.

Solve Today's Challenge →