JavaScript :
Single-Threaded Yet
Asynchronous
FEBRUARY 2025
EPAM Proprietary & Confidential.
Contents 01 Introduction to JavaScript ’s Single Threaded Model
02 Understanding Synchronous Code Execution
03 Introduction to Asynchronous JavaScript
04 JavaScript Callbacks
05 JavaScript Promises
06 Async/Await
07 Web Workers
EPAM Proprietary & Confidential. 2
01
Introduction to JavaScript ’s Single
Threaded Model
EPAM Proprietary & Confidential. 3
01 Introduction to JavaScript ’s Single Threaded Model
What is a Thread and why it matters ?
A thread is the smallest unit of execution within a process. In
simple words : An independent operation which is a part of
parent program.
Why Does It Matter?
Concurrency & Parallelism – Enables multitasking,
improving performance.
Efficient Resource Use – Multiple threads in a process
share memory and resources
Asynchronous Execution – Essential for non-blocking
operations in single-threaded environments (e.g., JavaScript
Event Loop).
EPAM Proprietary & Confidential. 4
01 Introduction to JavaScript ’s Single Threaded Model
JavaScript is a Single Threaded Scripting Language
JavaScript runs code synchronously, means Line (i) must
be processed before Line (i+1). This works well for simple
operations but creates problems when dealing with:
● Time-consuming tasks like file reading and API
requests.
● Blocking operations like loops or calculations that
freeze the page.
Since JavaScript runs on a single thread, a long-running
synchronous task blocks the main thread, making the
web page unresponsive.
EPAM Proprietary & Confidential. 5
02
Understanding Synchronous Code
Execution
EPAM Proprietary & Confidential. 6
02 Understanding Synchronous Code Execution
Synchronous Execution of the code.
Now that we understand synchronous execution, let's see its
impact in real world and how it affects the User Experience
Key Issue with Sync Code: It blocks the main thread, causing the UI to
freeze until execution is complete.
Difference ?
✅ Sync Execution (Blocks UI) – The page becomes unresponsive.
✅ Async Execution (Non-blocking) – The UI stays smooth, even while
the task runs.
Imagine a website where clicking a button locks the entire page for a few
seconds—frustrating, right? 😡
EPAM Proprietary & Confidential. 7
02 Understanding Synchronous Code Execution
Problem with Sync Execution (Blocking Nature)
Let’s check my Editor !
This makes the UI unresponsive since
everything is executed one after another.
[Sync_Async.htmI]
EPAM Proprietary & Confidential. 8
02 Understanding Synchronous Code Execution
So, Why Did This Happen?
What we just saw wasn’t magic—it’s how JavaScript’s execution model
works!
🔹 Synchronous Code → Runs line by line, blocking everything else until it finishes.
🔹 Asynchronous Code → Uses event loop & callbacks to handle tasks without blocking
execution.
This happens because JavaScript is single-threaded, meaning it can execute only one task at a
time in the main thread.
So, how does JavaScript handle multiple tasks efficiently without freezing?
Answer: the Event Loop!
EPAM Proprietary & Confidential. 9
03
Introduction to
Asynchronous JavaScript
EPAM Proprietary & Confidential. 10
03 Introduction to Asynchronous JavaScript
The Event Loop :
JavaScript uses the Event Loop to manage synchronous and asynchronous tasks
efficiently.
1. Call Stack (Main Stack) 2. Web APIs (Async Handling Layer)
● Holds synchronous tasks that are ● Handles asynchronous tasks like
executed one at a time. setTimeout, fetch, event listeners, and
● Functions get pushed onto the stack DOM interactions.
when called and popped when they These tasks are sent to the browser’s Web
finish. APIs instead of blocking the Call Stack.
EPAM Proprietary & Confidential. 11
03 Introduction to Asynchronous JavaScript
The Event Loop :
3. Task Queues (Side Stack ) 4. Event Loop (The Traffic Controller)
Stores asynchronous tasks waiting to Constantly checks:
execute.
Question: Is the Call Stack empty?
Two types of queues:
✅ Are there tasks in the Microtask Queue?
✅ Microtask Queue → Handles → If yes, they run first.
Promises, queueMicrotask() (Higher priority).
✅ Are there tasks in the Macrotask
✅ Macrotask Queue → Handles Queue? → Runs them only after microtasks
setTimeout, setInterval, event listeners. are cleared.
EPAM Proprietary & Confidential. 12
Microtask and Macrotask Queue
Lets see
it live :
Macro_Micro.html
EPAM Proprietary & Confidential. 13
The Diagram
EPAM Proprietary & Confidential. 14
04
JavaScript Callbacks
EPAM Proprietary & Confidential. 15
04 JavaScript Callbacks
Callbacks
🔹 Scenario 1: Synchronous Execution (Boring Way)
👉 You ordered a Pizza
👉 Chef does one thing at a time
👉 First he makes DOUGH , then Pizza sauce etc
👉 You stay there and LET HIM COOK !
Lets see it in action : Chef_Sync.js
EPAM Proprietary & Confidential. 16
04 JavaScript Callbacks
Callbacks
🔹 Scenario 2: Asynchronous Execution (Callbacks) –
Better Approach
👉 You ordered a pizza , chef started working.
👉 This Chef is Smart , He knows which task is going to take what
time hence manages everything parallelly.
👉 Chef is Done with Pizza – “ Hey Sunil, Pizza is ready ! 🍕”
Lets see it in action : Chef_Async.js
EPAM Proprietary & Confidential. 17
04 JavaScript Callbacks
Callbacks
🔹So, are we good ? (not yet) : Problem with Callbacks
Callbacks enables the asynchronous tasks but upon nested structure , they
give rise to “Callback Hell” and..
❌ Looks Overwhelming 🤯
❌ Debug is not easy 🧐
❌ Code maintenance is difficult 🔧
Lets see it in action : Chef_Hell.js
EPAM Proprietary & Confidential. 18
05
JavaScript Promises
EPAM Proprietary & Confidential. 19
05 JavaScript Promises
Promises
A Promise is an object that
represents the eventual
completion (or failure) of an
asynchronous operation.
Here:
● The callback function inside
new Promise is called
immediately.
● It will either resolve or reject
based on conditions.
EPAM Proprietary & Confidential. 20
05 JavaScript Promises
Promises
Every Promise takes a callback function with two parameters:
✅ resolve → Called when the operation succeeds
✅ reject → Called when the operation fails
Then, .then() and .catch() handle the output:
● .then() → Runs if resolve() is called.
● .catch() → Runs if reject() is called.
EPAM Proprietary & Confidential. 21
05 JavaScript Promises
Promises
🔹 Problem with Promises :
Promises solved callback hell, but:
❌ Chaining .then() can still get long 📜
❌ Error handling with .catch() is separate .
❌ Readability still feels like extra work .
EPAM Proprietary & Confidential. 22
06
JavaScript - Async/Await
EPAM Proprietary & Confidential. 23
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
🔹 Solution: Async/Await (Syntactic Sugar Over Promises)
👉 async function → Always returns a Promise.
👉 await keyword → Waits for the Promise to resolve.
👉 No .then() chaining, making it look like synchronous code.
EPAM Proprietary & Confidential. 24
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
🔹 Sample Code with Async-Await:
1⃣ Function is marked as
async, so it can use
await.
2⃣ await waits for the
promise to resolve before
moving to the next line.
3⃣ No .then() needed,
code reads like normal
sync code!
EPAM Proprietary & Confidential. 25
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
🔹 Handling Errors Properly:
Promises use .catch(),
but Async/Await uses
try...catch for better
debugging.
EPAM Proprietary & Confidential. 26
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
Parallel Execution with [Link]()
Lets see it in action : Promise_All.js
EPAM Proprietary & Confidential. 27
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
Async_Await_New.js Promise_Chaining_Old.js
is generally better due to its improved It uses promise chaining to handle
readability, maintainability, and modern asynchronous operations for making a
approach to handling asynchronous pizza.
operations.
While this approach works, it can become
Therefore, it is recommended to use the harder to read and maintain as the
async/await syntax for handling number of chained promises increases.
asynchronous tasks.
EPAM Proprietary & Confidential. 28
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
So are we good now ? NO !!
“ Non Blocking of Code != Parallelism ”
~ Stack Overflow
It’s Just Concurrency , making you think that IT’S PARALLEL PROCESSING .
Then How to Get True Parallelism ?
Answer : Web Workers
EPAM Proprietary & Confidential. 29
06 Async/Await
Async/Await – The Modern Way to Handle Async Code
Concurrency vs Parallelism
EPAM Proprietary & Confidential. 30
07
JavaScript - Web Workers
EPAM Proprietary & Confidential. 31
07 Web Workers
JavaScript’s Single-Threaded Nature
🔹 The Reality of JavaScript’s Execution Model
✅ JavaScript is synchronous & single-threaded by design.
✅ It can handle async tasks using Promises, async/await, and callbacks.
✅ BUT... These tools do not enable true parallelism—they just allow
non-blocking execution.
💡 What Async Tools Actually Solve?
🔹 Promises & async/await → Handle delayed responses (e.g., fetching data).
🔹 They prevent blocking but don’t execute multiple things at once.
🔹 Analogy: A chef waiting for an ingredient doesn’t stand still but prepares
something else
EPAM Proprietary & Confidential. 32
07 Web Workers
Web Workers – The Solution for True Parallelism
🔹 The Need for Web Workers
✅ Unlike Promises, Web Workers allow JavaScript to run code on a separate thread.
✅ They are useful for CPU-intensive tasks (e.g., heavy computations, image processing).
🔹 How Web Workers Work
1⃣ A separate worker thread is created.
2⃣ The main thread communicates with the worker via messages.
3⃣ Once the worker finishes, it sends the result back.
🔹 The Role of Promises & Async/Await
✅ Even with workers, we still use Promises to wait for the result asynchronously.
✅ The worker executes independently, but the main thread does not know when it will
finish.
EPAM Proprietary & Confidential. 33
07 Web Workers
Web Workers – Visualized
Lets see it live : [Link]
EPAM Proprietary & Confidential. 34
Thank You
EPAM Proprietary & Confidential. 35