JavaScript Promises Interview Questions
One of the most frequently asked JavaScript interview questions is:
What is a Promise and why do we need it?
Interviewers often ask:
- What problems do Promises solve?
- What are Promise states?
- How does Promise chaining work?
- How does Promise error handling work?
- What is the difference between
Promise.all()andPromise.allSettled()? - How do Promises interact with the Event Loop?
- How is async/await related to Promises?
Let's understand Promises from first principles.
1. Why Do We Need Promises?
Before Promises, asynchronous JavaScript was commonly written using callbacks.
Example:
getUser(function (user) {
getPosts(user.id, function (posts) {
getComments(posts[0].id, function (comments) {
console.log(comments);
});
});
});This creates:
Callback HellProblems:
- Deep nesting
- Difficult error handling
- Harder debugging
- Poor readability
- Difficult composition
Promises were introduced to make asynchronous code more manageable.
2. What is a Promise & Its States
A Promise is an object that represents the eventual completion or failure of an asynchronous operation.
Think of a Promise as:
A Placeholder
For A Future ValueExample:
const promise = fetch("/users");At this moment:
Data Is Not Available YetThe Promise represents the future result.
Real-Life Analogy
Imagine ordering food online.
Order Placed
↓
Food Being Prepared
↓
DeliveredA Promise works similarly:
Pending
↓
Fulfilled
or
RejectedPromise States
Every Promise exists in one of three states.
Pending
Operation Still RunningFulfilled
Operation Completed SuccessfullyRejected
Operation FailedVisual Representation
Pending
/ \
/ \
Fulfilled RejectedA Promise can change state only once.
3. Creating a Promise
Example:
const promise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Success");
} else {
reject("Failed");
}
});Resolve
resolve(value);Marks the Promise as:
FulfilledReject
reject(error);Marks the Promise as:
Rejected4. Consuming a Promise & Error Handling
promise.then((result) => {
console.log(result);
});Output:
SuccessHandling Errors
promise.catch((error) => {
console.error(error);
});Output:
FailedComplete Example
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data Loaded");
}, 1000);
});
promise.then((data) => {
console.log(data);
});Output after 1 second:
Data Loaded5. Promise Chaining & Flow Visualization
One of the biggest advantages of Promises.
Example:
fetchUser()
.then((user) => {
return fetchPosts(user.id);
})
.then((posts) => {
return fetchComments(posts[0].id);
})
.then((comments) => {
console.log(comments);
});Instead of:
Nested Callbackswe get:
Linear FlowHow Chaining Works
Every:
.then()returns a new Promise.
Example:
Promise.resolve(5)
.then((value) => {
return value * 2;
})
.then((value) => {
console.log(value);
});Output:
10Promise Chain Visualization
Promise
↓
then()
↓
then()
↓
then()Each step receives the previous result.
Error Handling in Chains
Example:
fetchUser()
.then((user) => {
throw new Error("Failed");
})
.catch((error) => {
console.log(error.message);
});Output:
FailedWhy This Is Powerful
A single:
.catch()can handle errors from the entire chain.
Example:
task1().then(task2).then(task3).catch(handleError);Much cleaner than nested callbacks.
6. Execution Order & Event Loop Priority
What is the output?
console.log("Start");
const promise = new Promise((resolve) => {
console.log("Inside");
resolve();
});
console.log("End");Answer
Output:
Start
Inside
EndImportant:
Promise Constructor Executes ImmediatelyMany developers incorrectly assume it is asynchronous.
Event Loop Interview Question
What is the output?
console.log("1");
Promise.resolve().then(() => {
console.log("2");
});
console.log("3");Answer
Output:
1
3
2Why?
.then()creates a:
MicrotaskMicrotasks execute after synchronous code completes.
Promise vs setTimeout
What is the output?
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
Promise.resolve().then(() => {
console.log("3");
});
console.log("4");Answer
Output:
1
4
3
2Why?
Execution order:
Sync Code
↓
Microtasks
↓
MacrotasksPromises use:
Microtask QueueTimers use:
Macrotask Queue7. Parallel Promises: Promise.all vs. allSettled vs. race vs. any
Runs multiple Promises concurrently.
Example:
Promise.all([fetchUsers(), fetchPosts(), fetchComments()]);Behavior:
Wait For AllExample
Promise.all([Promise.resolve("A"), Promise.resolve("B")]).then((result) => {
console.log(result);
});Output:
["A", "B"]Promise.all Failure Behavior
Promise.all([Promise.resolve("A"), Promise.reject("Error")]);Output:
RejectedOne failure rejects the entire Promise.
Promise.allSettled()
Waits for all Promises regardless of success or failure.
Example:
Promise.allSettled([Promise.resolve("A"), Promise.reject("Error")]);Output:
[
{
status: "fulfilled",
value: "A",
},
{
status: "rejected",
reason: "Error",
},
];Promise.race()
Returns the first settled Promise.
Example:
Promise.race([fetchUsers(), timeout()]);Useful for request timeouts.
Promise.any()
Returns the first fulfilled Promise.
Example:
Promise.any([api1(), api2(), api3()]);Success from any source wins.
Promise.finally()
Runs regardless of success or failure.
Example:
fetchData()
.then(handleSuccess)
.catch(handleError)
.finally(() => {
hideLoader();
});Useful for cleanup.
8. Promises vs. Async/Await
Promise:
fetchUser()
.then((user) => {
return fetchPosts(user.id);
})
.then(console.log);Async/Await
const user = await fetchUser();
const posts = await fetchPosts(user.id);
console.log(posts);Cleaner syntax.
Important Interview Point
Async/Await:
Does Not Replace PromisesInstead:
Built On Top Of Promises9. Common Interview Q&A
Can a Promise Change State Twice?
No.
Example:
resolve("A");
resolve("B");
reject("Error");Only the first state change matters.
Does Creating a Promise Make It Asynchronous?
No.
The Promise constructor executes immediately.
What Queue Do Promise Callbacks Use?
Microtask QueueWhat Happens If a Then Callback Returns a Promise?
The next .then() waits for that Promise to settle.
What Happens If a Then Callback Throws?
The Promise becomes rejected.
The error propagates to the nearest .catch().
Senior-Level Interview Answer
A Promise is an object that represents the eventual completion or failure of an asynchronous operation. It can be in one of three states: pending, fulfilled, or rejected. Promises solve callback hell by providing a structured way to compose asynchronous operations through chaining. Methods such as
then,catch, andfinallyallow success handling, error handling, and cleanup. Promise callbacks are scheduled in the Microtask Queue, which gives them higher priority than timer callbacks in the Event Loop. Modern async/await syntax is built on top of Promises and provides a cleaner way to write asynchronous code.
Common Interview Mistakes
❌ "Promises are asynchronous."
Correct:
Promise callbacks are asynchronous.
The Promise constructor executes immediately.❌ "Async/Await replaces Promises."
Correct:
Async/Await is built on top of Promises.❌ "Promise.all waits even if one Promise fails."
Correct:
Promise.all rejects immediately
when any Promise rejects.❌ "Promises use the Callback Queue."
Correct:
Promises use the Microtask Queue.Promise API Summary
| API | Behavior |
|---|---|
| Promise.resolve() | Creates fulfilled Promise |
| Promise.reject() | Creates rejected Promise |
| Promise.all() | Waits for all Promises |
| Promise.allSettled() | Waits for all results |
| Promise.race() | First settled Promise wins |
| Promise.any() | First fulfilled Promise wins |
| finally() | Runs regardless of outcome |
Key Takeaways
- Promise States: A Promise represents an async operation that exists in one of three states: pending, fulfilled, or rejected.
- Chaining: Methods like
thenandcatchreturn new Promises, preventing nesting and resolving callback hell. - Event Loop Priority: Promise callbacks are processed inside the Microtask Queue, prioritizing them over standard timers.
- Parallel APIs: Use
Promise.allfor parallel operations, andPromise.allSettledto fetch resources without cascading failures.