Some tasks take time: loading data from a server, reading a file or waiting for a timer. JavaScript doesn't stop and wait for them. It carries on with other work and deals with the result later. A Promise is an object that represents that future result: "I promise to give you a value, or an error, when it's ready."
Without this approach, a page would freeze every time it loaded data, and visitors couldn't scroll or click until the network replied. Promises let the page stay responsive. They can feel abstract at first, so this lesson uses a simple analogy and small examples before you use them for real with fetch.
The three promise states
A promise is always in one of three states:
- pending: still waiting.
- fulfilled: finished successfully, with a value.
- rejected: failed, with an error.
Once a promise is fulfilled or rejected, it's settled, and its result never changes again.
Using a promise with then, catch and finally
fetchSomething()
.then(result => { /* success */ })
.catch(error => { /* failure */ })
.finally(() => { /* either way */ });.then()runs when the promise is fulfilled and receives the value..catch()runs when it's rejected, or when anything earlier in the chain throws an error..finally()runs at the end either way, which makes it ideal for hiding a loading spinner.
Whatever a .then returns is passed to the next .then, so you can chain several steps one after another. Always end a chain with .catch(), or failures will go unnoticed.
Creating your own promise
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));Inside new Promise((resolve, reject) => { … }), call resolve(value) for success or reject(error) for failure. Most of the time you'll use promises that other functions give you, like fetch, but making one yourself helps you understand how they work.
Running several promises together
Promise.all([p1, p2])waits for all of them and fails if any fails. The results arrive as an array in the same order.Promise.allSettled([…])waits for all of them and tells you which succeeded and which failed.Promise.race([…])settles with whichever finishes first.
Promise.all is useful when a page needs several pieces of data at once. Starting all the requests together is much faster than waiting for each one in turn.
JavaScript Promises Syntax
Promise basics
const p = new Promise((resolve, reject) => {
// async work…
resolve("done"); // or reject(new Error("failed"))
});
p.then(value => console.log(value))
.catch(error => console.error(error))
.finally(() => console.log("finished"));JavaScript Promises Summary
- A promise represents a result that will arrive later.
- Promises are pending, then either fulfilled or rejected.
.thenhandles success,.catchhandles errors and.finallyruns either way.- Values returned from
.thenpass down the chain. Promise.allruns several tasks at once and waits for them all.
JavaScript Promises Examples
Each example runs in the page. Edit the code and press Run to see what changes.
Promises don't block
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
console.log("1. Ordering pizza…");
wait(1000).then(() => {
console.log("3. 🍕 Pizza arrived!");
});
console.log("2. Setting the table while we wait");Line-by-line explanation
- Line 1A helper that returns a promise which resolves after
msmilliseconds. - Lines 5 to 7Schedule what to do when the promise fulfils.
- Line 9Runs immediately. The code didn't stop and wait.
Success, failure and chaining
Run it a few times. The "dice" sometimes fails.
function rollDice() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const n = Math.ceil(Math.random() * 6);
if (n === 1) reject(new Error("Rolled a 1. You lose!"));
else resolve(n);
}, 300);
});
}
rollDice()
.then(n => {
console.log("Rolled", n);
return n * 10;
})
.then(points => console.log("Points:", points))
.catch(error => console.log("❌", error.message))
.finally(() => console.log("Game over"));Line-by-line explanation
- Line 2Return a new promise.
- Lines 5 to 6Reject with an error on a 1, otherwise resolve with the number.
- Lines 12 to 15The first
thengets the number and returns points… - Line 16…which the next
thenreceives. - Line 17Any rejection skips to
catch. - Line 18
finallyalways runs.
Promise.all
const wait = (ms, value) => new Promise(res => setTimeout(() => res(value), ms));
console.log("Loading profile, posts and friends…");
const start = Date.now();
Promise.all([
wait(500, { name: "Ola" }),
wait(800, ["post 1", "post 2"]),
wait(300, 42),
]).then(([profile, posts, friendCount]) => {
console.log(profile.name, posts.length, "posts", friendCount, "friends");
console.log("Took about", Math.round((Date.now() - start) / 100) * 100, "ms");
});Line-by-line explanation
- Lines 6 to 10Three tasks start at the same time.
- Line 10Results arrive together, in the same order, destructured.
- Line 12Total time ≈ the slowest task (800ms), not the sum (1600ms).
Common JavaScript Promises Mistakes
Forgetting to return in a chain
getUser()
.then(user => { getPosts(user.id); }) // result lost!
.then(posts => console.log(posts)); // undefinedgetUser()
.then(user => getPosts(user.id))
.then(posts => console.log(posts));No catch
loadData().then(show);loadData().then(show).catch(err => showError(err));Unhandled rejections show up as "Uncaught (in promise)" errors and the user sees nothing happen.
Expecting the value immediately
const data = fetchData(); // a Promise, not the data
console.log(data.name); // undefinedfetchData().then(data => console.log(data.name));
// or, inside an async function: const data = await fetchData();JavaScript Promises in Real Projects
Promises power the network
fetch, reading files, camera access, location and database calls in Node.js all use promises in modern APIs. Most code today uses the friendlier async/await syntax, which is built on promises. That's the next lesson.
JavaScript Promises Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Handle success and failure.
loadScores()
.(scores => console.log(scores))
.(error => console.log("Failed:", error.message));
then for success, catch for errors.In what order are the numbers logged?
console.log(1);
Promise.resolve().then(() => console.log(2));
console.log(3);.then callbacks always run after the current code finishes.What does Promise.all do if one promise rejects?
The chain should log Total: 30. A value is being lost. Fix it.
Promise.resolve(10)
.then(n => {
n * 3;
})
.then(total => console.log("Total:", total));- Logs "Total: 30"
JavaScript Promises Quiz
3 questions to check what you learned.
Which state is a promise in while it's still waiting?
- pending
- fulfilled
- rejected
- loading
What does
.finally()do?- Runs only on success
- Runs only on failure
- Cancels the promise
- Runs after the promise settles, whether it succeeded or failed
Promise.all([wait(1000), wait(2000)])takes about how long?- 1 second
- 2 seconds
- 3 seconds
- 0 seconds
JavaScript Promises Challenge
Make a delay function
Write delay(ms, value) that returns a Promise which resolves with value after ms milliseconds.
Then use it: delay(200, "Ready!").then(msg => console.log(msg));
function delay(ms, value) {
// return a new Promise…
}
delay(200, "Ready!").then(msg => console.log(msg));- delay returns a Promise
- It resolves with the value
- It actually waits
- Logs "Ready!"