Promises

What it does: An object that represents the eventual completion (or failure) of an async operation and its resulting value.

Creating Promises:

Basic Structure:

let promise = new Promise((resolve, reject) => {
  // Do async work here
  if (success) {
    resolve(data);  // Promise becomes "fulfilled"
  } else {
    reject(error);  // Promise becomes "rejected"
  }
});

Key Rule: You MUST call either resolve() OR reject() - never both, never neither.

Three States:

  • Pending: Initial state, not yet completed
  • Fulfilled: Operation completed successfully
  • Rejected: Operation failed

Consuming Promises:

.then() takes 2 callbacks:

promise.then(
  data => console.log(data),    // success: gets actual result
  error => console.log(error)   // failure: gets Error object
);

.catch() for errors only:

promise.catch(error => console.log(error));
// Same as: promise.then(null, error => ...)

.finally() runs regardless:

promise.finally(() => console.log("cleanup"));
// No parameters, always runs after resolve/reject

Interview Gotchas:

// 1. Executor runs immediately
new Promise(resolve => {
  console.log("Runs now!"); // logs immediately
  resolve("done");
});
 
// 2. Can't resolve twice
new Promise(resolve => {
  resolve("first");
  resolve("second"); // ignored!
});
 
// 3. Handlers work on settled promises
let done = Promise.resolve("finished");
done.then(console.log); // runs immediately
 
// 4. finally passes through values
promise
  .finally(() => "ignored")
  .then(result => console.log(result)); // gets original result

Bottom line: Promises have 3 states (pending → fulfilled/rejected), executor runs immediately, and you chain handlers with .then/.catch/.finally.