An asynchronous operation gives you a Promise now, but its value or error arrives later. Logging the Promise is not consuming its result. Beginners can use the complete JavaScript learning path. Promises move from pending to one settled outcome, schedule handlers after synchronous work, pass values through chains, and coordinate concurrent operations.
What a JavaScript Promise represents
A Promise represents the eventual completion or failure of an asynchronous operation. It starts pending, then becomes fulfilled with one value or rejected with one reason. Either outcome is settled; later settlement calls cannot change it.
const lesson = Promise.resolve({ id: "JS-17", exercises: 3 });
console.log(lesson instanceof Promise); // true
lesson.then(value => console.log(value.id, value.exercises)); // JS-17 3lesson is the Promise wrapper; value is the fulfilled object delivered later. Promises coordinate browser and server-side JavaScript, but network work is not part of the language. Explore Coding & Skills, or review browser and HTTP context in Web Technologies for Teaching Exams: HTML and HTTP.
Create a Promise and predict its exact execution order
console.log("A: before");
const ticket = new Promise(resolve => {
console.log("B: executor");
setTimeout(() => resolve("P-17"), 200);
});
ticket.then(value => console.log("D: resolved", value));
console.log("C: after");The output is:
A: before
B: executor
C: after
D: resolved P-17The executor runs synchronously. The timer makes resolution eligible after at least 200 ms, not at an exact wall-clock time. The handler follows current synchronous work.

Handle fulfilment, rejection, and cleanup
function checkSeats(requested) {
const available = 3;
return new Promise((resolve, reject) => {
if (requested <= available) resolve(`Reserved ${requested} of ${available} seats`);
else reject(new Error("Only 3 seats available"));
});
}Even immediate settlement does not run handlers in the current stack. Run each branch separately:
checkSeats(2)
.then(console.log)
.catch(error => console.log(error.message))
.finally(() => console.log("Seat check complete"));
// Reserved 2 of 3 seats
// Seat check complete
checkSeats(5)
.then(console.log)
.catch(error => console.log(error.message))
.finally(() => console.log("Seat check complete"));
// Only 3 seats available
// Seat check complete.then transforms success, .catch handles earlier rejection, and .finally runs cleanup without receiving or replacing the result unless it throws or returns a rejected Promise. A normal catch return fulfils the chain.
Worked example: chain a two-seat booking from result to total
function reserveSeats(requested) {
const available = 3;
return new Promise((resolve, reject) => {
setTimeout(() => {
if (requested <= available) {
resolve({ reservationId: "R-42", seats: requested, farePerSeat: 350 });
} else {
reject(new Error("Only 3 seats available"));
}
}, 120);
});
}
reserveSeats(2)
.then(booking => ({
...booking,
subtotal: booking.seats * booking.farePerSeat
}))
.then(booking => Promise.resolve({
...booking,
bookingFee: 35,
total: booking.subtotal + 35
}))
.then(booking => console.log(
`${booking.reservationId}: ${booking.seats} seats, total ${booking.total}`
))
.catch(error => console.log(`Booking failed: ${error.message}`));The handlers calculate 2 * 350 = 700, then 700 + 35 = 735, producing R-42: 2 seats, total 735. The 120 ms delay is a teaching simulation. A plain return passes its value; Promise.resolve(...) makes the chain wait. Errors skip success handlers until a catch, keeping the chain flat.
A separate reserveSeats(5) call with the same handlers prints Booking failed: Only 3 seats available.

Coordinate several Promises with the right combinator
Promises start when created, so make fresh sources for every demonstration:
function makeSources() {
return {
cache: new Promise((_, reject) =>
setTimeout(() => reject(new Error("cache miss")), 100)),
api: new Promise(resolve => setTimeout(() => resolve("api data"), 250)),
backup: new Promise(resolve => setTimeout(() => resolve("backup data"), 150))
};
}For each row, call makeSources() and pass [cache, api, backup].
Helper | Completion condition | Exact result |
|---|---|---|
| Every input fulfils, or one rejects | Rejects with |
| Every input settles | Rejected |
| First input settles | Rejects with |
| First input fulfils | Fulfils with |
all and race reject on the 100 ms cache timer. any fulfils on the 150 ms backup timer. allSettled waits through the 250 ms API timer.
Use all for every result, allSettled for a complete report, race for the first settlement, and any for the first success. any rejects with an AggregateError only if all reject. Fulfilled all values preserve input order. Helpers coordinate but do not cancel operations.
Common Promise mistakes and their observable failures
This missing return prints undefined:
Promise.resolve(4)
.then(n => { Promise.resolve(n * 3); })
.then(console.log);Return Promise.resolve(n * 3), or use n => Promise.resolve(n * 3), to print 12. Starting an inner Promise does not connect it.
new Promise((resolve, reject) => {
resolve("first");
reject(new Error("second"));
resolve("third");
}).then(console.log); // firstA Promise settles once. Do not use repeated settlement as control flow. Use an early return after choosing a branch.
Trap | Observable failure | Repair |
|---|---|---|
| Calls | Pass |
No rejection handler | Can surface an unhandled rejection | Handle it deliberately or return the chain to a caller |
| Next link fulfils with | Log, then |
How assessments and interviews test Promises
Common assessments ask you to predict output, trace values, choose a combinator, repair a missing return, or convert a chain to async/await.
Promise.resolve(5).then(n => n + 2).then(n => n * 3).then(console.log)prints21, because(5 + 2) * 3 = 21.Promise.reject("E").catch(() => 4).then(console.log)prints4, because the catch recovers with a fulfilled value.console.log(1); Promise.resolve().then(() => console.log(3)); console.log(2);prints1,2,3, because the handler waits for synchronous code.
For wider timed preparation, use this Coding Round Strategy for Placements.
Exercise 1: implement loadPrice(quantity) so loadPrice(4).then(price => price + 5) fulfils with 125, but zero rejects.
function loadPrice(quantity) {
if (quantity <= 0) return Promise.reject(new Error("Quantity must be positive"));
return Promise.resolve(quantity * 30);
}
loadPrice(4).then(price => price + 5).then(console.log);
// 4 * 30 = 120, then 120 + 5 = 125, so it prints 125Exercise 2: rewrite the successful booking with async/await.
async function quoteTotal() {
const booking = await reserveSeats(2);
return booking.seats * booking.farePerSeat + 35;
}
quoteTotal().then(console.log); // 2 * 350 + 35 = 735
async function quoteRejected() {
try { await reserveSeats(5); }
catch (error) { console.log(error.message); }
}
quoteRejected(); // Only 3 seats availablePromises in JavaScript: the short version and next step
A Promise starts pending.
It settles once.
.thentransforms success..catchhandles failure.Returned values and Promises connect chain links.
Retype the R-42 chain and its 700 + 35 = 735 flow. Request three seats, predict subtotal: 1050 and total: 1085, then run it. Request four and predict Only 3 seats available. Explain why no total handler runs.
Beginners can continue with the Complete JavaScript course named above. Later, apply these patterns through the MERN Stack full-stack development course. Predict every transition before running the chain.




