Asynchrony in JavaScript
Asynchrony in JavaScript is a mechanism that lets tasks run without blocking the main thread. In plain words, JavaScript does not have to wait for long operations to finish (server requests, file reads or timers), it keeps executing the rest of the code and handles the result later, when it is ready.
Theory
TL;DR
- JavaScript is a single threaded language: code runs sequentially, one task at a time.
- Asynchrony exists so that long operations do not «freeze» the page.
- Asynchrony is not parallelism, it is a task scheduling mechanism.
- It is implemented through the Event Loop, the call stack, Web APIs and the task queue.
- The main ways to work with it are callbacks, promises and
async/await. awaitpauses execution inside a function but does not block the thread.
Quick example
console.log('1');
setTimeout(() => {
console.log('2'); // runs later
}, 1000);
console.log('3');Output:
1
3
2This happens because setTimeout is an asynchronous operation: it is «put in a queue» and runs after the main code, one second later.
Synchronous code and blocking
console.log('1');
alert('Please wait...'); // blocks execution
console.log('2');Until the user closes the alert, the program is stopped, this is synchronous code. Asynchrony removes exactly this behaviour: a long operation no longer holds the main thread.
How it works under the hood
Asynchrony in JS is implemented through the Event Loop.
- The main code runs in the call stack.
- Asynchronous operations (timers,
fetch, events and so on) are handed over to Web APIs (the browser or Node.js API). - When an operation finishes, its callback goes into the callback queue.
- The Event Loop checks whether the stack is free, and if it is, takes a task from the queue and runs it.
So asynchrony is not «parallelism», it is a task scheduling mechanism.
The main ways to work with asynchrony
| Approach | Example | Notes |
|---|---|---|
| Callbacks | setTimeout(() => {...}, 1000) | Old, inconvenient (callback hell) |
| Promises | fetch(...).then(...) | More modern, more readable |
| async / await | const data = await fetch(...) | The most convenient syntax |
An example with a Promise:
fetch('https://api.example.com/user')
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));fetch returns a Promise, a promise that the result will be delivered in the future, and it can be handled with .then().
An example with async/await:
async function loadUser() {
try {
const res = await fetch('https://api.example.com/user');
const user = await res.json();
console.log(user);
} catch (e) {
console.error(e);
}
}
loadUser();await «stops» execution inside the function until the promise settles, but it does not block the thread. Asynchrony is preserved.
Typical asynchronous operations in JS
setTimeout,setIntervalfetch()(network requests)- File work in Node.js (
fs.promises) - Events (
addEventListener) - WebSocket, IndexedDB, Web Workers and so on
Summary of terms
| Term | What it means |
|---|---|
| Asynchrony | Running tasks «in the background» without blocking the main thread |
| Event Loop | The mechanism that drives the task queue |
| Callback Queue | The queue of tasks ready to run |
| Promise | An object that represents the result of an asynchronous operation |
| async / await | Convenient syntax for working with promises |
Common mistakes
- Confusing asynchrony with multithreading: no second thread appears for your code, only the order of execution changes.
- Believing that
setTimeout(fn, 1000)guarantees exactly one second: it is a minimum delay, the task waits until the stack is free. - Blocking the main thread with a heavy synchronous loop and then being surprised that asynchronous callbacks do not fire on time.
- Forgetting error handling: a promise without
.catch()ortry...catchproduces an unhandled rejection. - Mixing callbacks and promises in one chain instead of bringing everything to
async/await.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.