Overview

8 Functions for the future: promises and generators

The chapter introduces promises as the modern JavaScript way to represent future results, especially for asynchronous work that once relied on callbacks. A promise can be consumed with then, but more importantly it can be passed around, chained, and combined with others to build higher-level workflows. The text explains how promises move from pending to fulfilled or rejected states, how resolution works with plain values and thenables, and why utilities like Promise.withResolvers() make it easier to bridge callback-based APIs with promise-based code.

It then shows how promise chaining improves readability and error handling, especially when compared with deeply nested callbacks. Methods like catch and finally provide clean equivalents to try/catch/finally, while static methods such as Promise.all, Promise.allSettled, Promise.any, and Promise.race help coordinate concurrent operations. The chapter also clarifies timing behavior by distinguishing microtasks from macrotasks, explaining why promise callbacks run before setTimeout callbacks and how this fits into JavaScript’s single-threaded event loop.

Finally, the chapter presents await and async as the syntax that makes promise-based code feel synchronous without blocking the thread. await pauses an async function until a promise settles, then resumes with the fulfilled value or throws the rejection reason, while async functions automatically wrap returned values in promises and convert thrown errors into rejections. The chapter closes by revisiting generators: functions that can pause and resume execution with yield, implement iterables and iterators, delegate with yield*, and, in async form, work with promises and for await...of to model streaming or stepwise asynchronous processes.

The possible states of a promise: pending, fulfilled, rejected. The value associated with the rejected state is often called a reason.
Add an asterisk (*) after the function keyword to define a generator function.

Summary

  • A promise is a placeholder for the result of a task, typically an asynchronous one. A promise can either be fulfilled or rejected. Once that’s happened, we say that it’s settled: It will permanently remain in the same state.
  • Asynchronous JavaScript APIs like fetch return a promise instead of taking a callback. We can attach as many callbacks as we want using the then method on the promise.
  • We can use utility functions like Promise.all and Promise.race to combine promises for tracking multiple tasks.
  • The await keyword waits for a promise to resolve, returning its fulfilled value or throwing its rejection reason.
  • The async keyword guarantees that a function will always return a promise. When the function returns a value or throws an error, it’ll be used to resolve the returned promise.
  • A generator function is declared by putting an asterisk (*) after the function keyword. Within the body of the generator, we can use the new yield keyword that yields a value and suspends the execution of the generator. If we want to yield to another generator, we use the yield* operator.
  • The object returned by a generator function is an iterable. Iterables have a next() method for advancing to the next result, but are more often used in for…of loops or destructured like an array.
  • The yield keyword works as a two-way binding with the generator’s next() method, allowing values to be returned from and passed into the generator.
  • We can combine generators with async and await to produce async iterators that can be used in for await…of loops.

FAQ

```html
What is a promise in JavaScript?A promise is an object that represents the outcome of an asynchronous operation. It starts in the pending state and later becomes either fulfilled or rejected.
What are the three states of a promise?A promise can be pending, fulfilled, or rejected. When it becomes fulfilled or rejected, it is considered settled.
What does it mean for a promise to be settled?A promise is settled when it has either been fulfilled or rejected. Once settled, its state and associated value no longer change.
How does then() work with promises?then() registers callbacks for fulfillment or rejection and returns a new promise. The returned promise is resolved based on what the callback returns or rejects if the callback throws.
Why is Promise.all() useful?Promise.all() combines multiple promises into one. It fulfills only when all promises fulfill, returning their values in the original order, and rejects immediately if any one promise rejects.
What is the difference between Promise.any() and Promise.race()?Promise.any() resolves with the first fulfilled promise, while Promise.race() settles with the first promise to settle, whether fulfilled or rejected.
How does await simplify promise handling?await lets you write promise-based code in a synchronous style. It pauses only the current async function or module until the promise settles, then resumes with the fulfilled value or throws on rejection.
What is an async function?An async function is a function declared with async that always returns a promise. Returned values are wrapped in a resolved promise, and thrown errors become rejected promises.
What is a generator function and how does yield work?A generator function is declared with function* and returns a generator object. The yield keyword pauses execution and produces a value each time next() is called.
What are async generators used for?Async generators combine async, await, and yield to produce values over time while waiting for asynchronous work. They are commonly consumed with for await...of.
```

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secrets of the JavaScript Ninja, Third Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secrets of the JavaScript Ninja, Third Edition ebook for free