JavaScript Promises: Lifecycle, Thenable Chaining & Promise Combinators

Introduced in ES6, a Promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value. Promises eliminate Callback Hell by enabling clean, linear method chaining and centralized error handling.

JavaScript Promise Lifecycle and State Transitions

Figure 9: The Promise Lifecycle: Pending state transitions to Fulfilled (.then) or Rejected (.catch), culminating in .finally().

Creating a Promise

const verifyEnrollment = (studentId) => {
    return new Promise((resolve, reject) => {
        console.log("Checking university registrar database...");
        setTimeout(() => {
            if (studentId > 0) {
                resolve({ id: studentId, status: "Enrolled", semester: 4 });
            } else {
                reject(new Error("Invalid Student ID provided."));
            }
        }, 1200);
    });
};

// Consuming the Promise:
verifyEnrollment(1042)
    .then(data => {
        console.log("Success:", data);
        return data.semester; // Value passed to next .then()
    })
    .then(sem => {
        console.log(`Student is active in Semester ${sem}`);
    })
    .catch(err => {
        console.error("Error Caught:", err.message);
    })
    .finally(() => {
        console.log("Operation Complete: Registrar connection closed.");
    });

Promise Combinators (Parallel Execution)

Combinator Method Behavior & Practical Use Case
Promise.all([p1, p2]) Waits for ALL to fulfill; rejects immediately if ANY single promise fails (All-or-nothing).
Promise.allSettled([p1, p2]) Waits for ALL promises to settle; returns status objects ({status: "fulfilled", value} or {status: "rejected", reason}).
Promise.race([p1, p2]) Settles as soon as the FIRST promise settles (either fulfills or rejects). Ideal for request timeouts!
Promise.any([p1, p2]) Resolves as soon as the FIRST promise fulfills successfully (ignores rejections until all fail).
// Running 3 independent network queries in parallel:
const fetchWeather = Promise.resolve("Sunny, 28°C");
const fetchNews = Promise.resolve("Campus Tech Fest Announced");
const fetchAlerts = Promise.resolve("No Alerts");

Promise.all([fetchWeather, fetchNews, fetchAlerts])
    .then(([weather, news, alerts]) => {
        console.log(`Dashboard: ${weather} | News: ${news}`);
    });

University Exam Corner (BCA Examination Notes)

Exam Question: "Where do Promise callbacks execute in the JavaScript Event Loop?"

Answer: Promise callbacks (registered in .then(), .catch(), and .finally()) are placed into the Microtask Queue. The Microtask Queue has higher priority than the Macrotask Queue (timers), meaning all pending promises execute immediately after the current synchronous script before any timer callback runs.

Next Step

How can we write asynchronous code that reads cleanly like synchronous statements? Proceed to: JavaScript Async / Await Syntax & Best Practices →

Explore Related JavaScript Tutorials

Accelerate your JavaScript mastery by studying these tightly connected core tutorials:

Async / Await Syntax →

Syntactic sugar for handling Promises cleanly.

Fetch API & HTTP →

Consuming REST APIs using Promise chains.

Microtasks & Macrotasks →

Why promise callbacks execute before timers.

Callback Patterns →

Comparing callbacks to modern promises.

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!