JavaScript Async Programming
JavaScript runs one task at a time.
While one task is running, no other JavaScript code can run. If a task takes a long time, the browser cannot respond to user actions until the task finishes.
Asynchronous programming solves this problem by allowing long-running operations to complete in the background while JavaScript continues running other code.
What Does "Async" Mean?
The word async means not at the same time.
Instead of waiting for one task to finish before starting the next, JavaScript can continue running other code while waiting for an operation to complete.
When the operation finishes, JavaScript continues by running code that handles the result.
Synchronous JavaScript
JavaScript executes code one line at a time.
By default, JavaScript executes statements one after another.
Each statement must finish before the next statement can begin.
Example
let x = 5;
let y = x * 2;
The output should be: A B C.
Control Flow
Control Flow is the order in which statements are executed in a program.
By default, JavaScript runs code from top to bottom and left to right.
Function Sequence
JavaScript functions are executed in the sequence they are called. Not in the sequence they are defined.
This example will display "Hello Goodbye" because the functions are called in that order:
Example
function myFirst() {
myDisplayer("Hello");
}
function
mySecond() {
myDisplayer("Goodbye");
}
myFirst();
mySecond();
This example will display "Goodbye Hello" because the functions are called in that order:
Example
function myFirst() {
myDisplayer("Hello");
}
function
mySecond() {
myDisplayer("Goodbye");
}
mySecond();
myFirst();
The examples above are normal synchronous flow.
Blocking Code
A long-running task blocks JavaScript.
While JavaScript is busy, it cannot respond to button clicks, keyboard input, or other events.
Example
The browser becomes unresponsive until the wait() function finishes:
function wait() {
let i = 2e9;
while (--i > 0);
}
wait();
myDisplayer("Done!");
Why Async Programming?
Some operations take time to complete:
- downloading data
- reading files
- waiting for events
- waiting for user input
- waiting for a timer
- Timers run after a specified number of milliseconds
- Events run when triggered by an event
- Network requests run when the data arrives
If JavaScript waited for these tasks, the page would freeze.
A frozen page is a broken page.
To stay responsive, JavaScript can use async programming.
Asynchronous flow refers to how JavaScript allows certain operations to run in the background and let their results be handled when they are ready.
Asynchronous Concepts
JavaScript handles asynchronus programming using different core concepts.
| Concept | Description |
|---|---|
| Synchronus | JavaScript standard flow is executing line by line. |
| Timers | Allows code to run while other code is waiting. |
| Callbacks | Callbacks were the first solution for async JavaScript. |
| Events | Stores callback function waiting to be executed. |
| Promises | Tools to handle asynchronous operations cleanly. |
| Async/Await | The clean and modern way to handle async code. |
Common Asynchronous Operations
| Operation | Example |
|---|---|
| Timer | setTimeout() |
| Network request | fetch() |
| User interaction | click events |
| Animation | requestAnimationFrame() |
| Web Workers | Background processing |
Ways to Handle Async Results
JavaScript has several ways to handle asynchronous results.
- Callbacks
- Promises
- Async functions and await
The next chapters explain each technique.
Summary
- JavaScript executes one task at a time.
- Long-running tasks can block a page in the browser.
- Asynchronous operations can prevent blocking.
- Asynchronous programming keeps applications responsive.
- Asynchronous behavior are provided by browser and JavaScript APIs like callbacks, promises, async and await.
Asynchronous vs Parallel
Parallel means doing multiple things at the same time on different processors.
Asynchronous means switching between tasks, not necessarily running them simultaneously.
A single-threaded JavaScript engine handles asynchronous tasks by using an event loop to switch between them, rather than utilizing multiple CPU cores. When a task finishes, it signals the main thread (via a callback, promise, or event) to handle the result.
| Feature | Async (Deferred) | Parallel (Simultaneous) |
|---|---|---|
| Goal | Responsiveness (Don't freeze) | Performance (Get it done faster) |
| Execution | Non-blocking (waiting for I/O) | Simultaneous (crunching many numbers) |
| Hardware | Can run on 1 processor | Requires multiple processors |
| Example | Running code while the user scrolls | Processing 10,000 images at once |
In short, asynchronous tells the system:
- Start this task now
- I don't need the result immediately
- Notify me later when it's done
Analogy:
Ordering food at a restaurant.
- Place your order (async call)
- Sit down and do other things while the chef makes it
- The server brings the food (callback)
What You Will Learn
This tutorial will build the understanding of async programming step by step:
- What are timeouts.
- Why callbacks were created.
- How promises represent future values.
- Why async and await are preferred.
- How to debug async code.
Each of these tools was created to solve problems from the previous tool.
Callbacks were the first solution for asynchronous JavaScript.