Loading...
Loading...
A value that will exist in the future. The foundation of modern async JavaScript.
Beyond the basics lie the tools professional JavaScript relies on daily: Promises for async work, classes for object-oriented design, Map and Set for specialized collections, and structured error handling for reliable applications.
A Promise represents a value that may not exist yet — pending, fulfilled, or rejected. Learn construction, .then/.catch/.finally chains, combinators, and how promises paved the way for async/await.
Once you are comfortable with functions and data structures, the next step is the patterns professional codebases use every day. Promises coordinate asynchronous work, classes organize related behavior, and try/catch keeps applications from crashing on unexpected input.
This module bridges beginner syntax and production-ready JavaScript. You will learn when to reach for Map instead of a plain object, how Set eliminates duplicates, and how error handling turns fragile scripts into reliable software.
Promises underpin every fetch call and async/await expression. Understanding chaining, error propagation, and Promise.all versus Promise.race is essential when debugging network code or reading framework internals.
Wrap an async operation in a Promise.
const promise = new Promise((resolve, reject) => { // Do async work... const success = true; if (success) { resolve("It worked!"); // → fulfilled } else { reject(new Error("Failed")); // → rejected } });
The Promise constructor takes an 'executor' function with resolve and reject. Call resolve for success, reject for failure.
Consuming promise results.
const promise = fetchData(); // .then() — runs on fulfillment: promise.then(data => { console.log("Got:", data); }); // .catch() — runs on rejection: promise.catch(error => { console.error("Failed:", error.message); }); // .finally() — runs ALWAYS (fulfilled or rejected): promise.finally(() => { hideLoadingSpinner(); // cleanup }); // Combined: fetchData() .then(data => process(data)) .catch(err => showError(err)) .finally(() => hideSpinner());
.then()
on success
.catch()
on error
.finally()
always
Each .then() returns a new promise. Chain sequential operations.
fetch("/api/user") .then(response => response.json()) // returns Promise .then(user => fetch(`/api/posts/${user.id}`)) // returns Promise .then(response => response.json()) // returns Promise .then(posts => console.log(posts)) // final value .catch(err => console.error(err)); // catches ANY error above
Each .then() receives the resolved value of the previous promise. If you return a Promise, the next .then() waits for it.
Orchestrate multiple promises running in parallel.
// Promise.all — wait for ALL to succeed const [users, posts, comments] = await Promise.all([ fetchUsers(), fetchPosts(), fetchComments() ]); // All three run in parallel! // Rejects immediately if ANY one fails
Runs all promises in parallel. Resolves with an array of all results. Fails fast — if any promise rejects, the whole thing rejects.
Promise callbacks run before setTimeout callbacks.
console.log("1. sync"); setTimeout(() => console.log("4. macrotask"), 0); Promise.resolve().then(() => console.log("3. microtask")); console.log("2. sync"); // Output order: // "1. sync" // "2. sync" // "3. microtask" ← Promise.then (microtask queue) // "4. macrotask" ← setTimeout (macrotask queue)
Execution priority:
1. Synchronous code (call stack)
2. Microtasks (.then, .catch, .finally, queueMicrotask)
3. Macrotasks (setTimeout, setInterval, I/O)
Common questions about promises & async.
Step through the code and watch variables change
1console.log("1 - Start");23const p = new Promise((resolve) => {4 console.log("2 - Inside Promise");5 resolve("done");6});78p.then((val) => {9 console.log("3 - Then:", val);10});1112console.log("4 - End");
1 - Start
"1 - Start" is logged synchronously. Synchronous code always runs first.
Test your understanding — 3 questions
What are the three states of a Promise?