JavaScript Promises

Master asynchronous operations with promises, chaining methods, async/await syntax, and parallel combinators.

TL;DR

  1. 01Use Promise instances to manage deferred asynchronous values.
  2. 02Chain then(), catch(), and finally() handlers to process values.
  3. 03Leverage async and await for synchronous-looking promise code.

Tips

  1. 01Run independent asynchronous processes concurrently using Promise.all() to prevent blocking call pipelines.
  2. 02Utilize Promise.allSettled() when you need results from all operations, including individual rejections.

Warnings

  1. 01Forgetting to return a value inside a then() block breaks the promise chaining sequence.
  2. 02A single rejected promise in Promise.all() rejects the entire collection immediately without waiting.

Creating Promises

    new Promise()

    Constructs a promise wrapper by passing resolve and reject callback handles.

    const p = new Promise((resolve, reject) => {
      if (success) resolve(data);
      else reject(new Error("Failed"));
    });
    Promise.resolve()

    Returns an already-fulfilled promise containing the supplied argument.

    Promise.resolve(42)
      .then(val => console.log(val));
    Promise.reject()

    Returns an already-rejected promise containing the supplied error reason.

    Promise.reject(new Error("Failed"))
      .catch(err => console.error(err));

Handling Results

    .then()

    Attaches a fulfillment handler to react when a promise resolves.

    promise.then(result => {
      console.log("Resolved:", result);
    });
    .catch()

    Attaches a rejection handler to catch errors thrown in chains.

    promise.catch(error => {
      console.error("Caught error:", error);
    });
    .finally()

    Attaches a callback that executes regardless of success or failure outcomes.

    promise.finally(() => {
      console.log("Operation completed");
    });

Promise Chaining

    Chaining .then()

    Passes the return value of each handler to the next link.

    fetch("/api/users/1")
      .then(res => res.json())
      .then(user => console.log(user.name))
      .catch(err => console.error(err));
    Sequential waiting

    Returns a new promise inside then to pause subsequent step execution.

    getUser(id)
      .then(user => getOrders(user.id))
      .then(orders => console.log(orders));
    Error recovery

    Attaches a catch block to supply fallback values and continue chaining.

    fetch("/api/data")
      .catch(() => getCachedData())
      .then(data => render(data));

Combining Promises

    Promise.all()

    Waits for all promises to resolve, rejecting instantly if any fail.

    const [a, b] = await Promise.all([p1, p2]);
    Promise.race()

    Returns the result of the first promise to settle, resolving or rejecting.

    const fastest = await Promise.race([p1, p2]);
    Promise.any()

    Returns the first successfully resolved promise, ignoring rejections.

    const firstOk = await Promise.any([p1, p2]);
    Promise.allSettled()

    Waits for all promises to settle and returns their status array.

    const results = await Promise.allSettled([p1, p2]);

Common Patterns

    Parallel execution

    Initiates independent promises simultaneously to speed up total execution times.

    const p1 = fetchUser();
    const p2 = fetchPosts();
    const [user, posts] = await Promise.all([p1, p2]);
    Promisifying callbacks

    Wraps a legacy callback function like setTimeout in a promise.

    const delay = ms => {
      return new Promise(r => setTimeout(r, ms));
    };
    await delay(1000);

In Practice

FAQ