liveBook · Manning

Asynchronous programming

As explained in Secrets of the JavaScript Ninja, Second Edition

Program code structured to handle operations that may complete after control has returned to the caller.

When a browser waits for several dependent requests, synchronous code can freeze the UI. Callbacks keep the interface responsive, but nested callbacks can add boilerplate and scatter error handling. section 6.1 section 6.4

Generators and promises offer another way to coordinate asynchronous work. A generator can yield while a promise is pending; when the promise settles, an iterator resumes the generator with the result. This keeps dependent steps readable without blocking, and allows errors to be handled with try/catch. section 6.4

Listing 6.19. Combining generators and promises
async(function*(){                                                      #A
  try {
    const ninjas = yield getJSON("data/ninjas.json");                   #B
    const missions = yield getJSON(ninjas[0].missionsUrl);              #B
    const missionDescription = yield getJSON(missions[0].detailsUrl);   #B
    //Study the mission details
  }
  catch(e) {                                                   #C
    //Oh no, we weren't able to get the mission details        #C
  }                                                            #C
});

function async(generator) {                                 #D
  var iterator = generator();                               #E

  function handle(iteratorResult) {                         #F
    if(iteratorResult.done) { return; }                     #G
    
    const iteratorValue = iteratorResult.value;
    
    if(iteratorValue instanceof Promise) {                  #H
      iteratorValue.then(res => handle(iterator.next(res))  #H
                   .catch(err => iterator.throw(err));      #H
    }                                                       #H
  }

  try {                                                     #I
    handle(iterator.next());                                #I
  }                                                         #I
  catch (e) { iterator.throw(e); }                          #I
}

Follow the generator’s dependent JSON requests and the helper that resumes it as each promise settles. section 6.4

The practical trade-off:

  • Synchronous requests are straightforward but block the UI; callbacks avoid blocking but can become awkward to read and maintain. section 6.1
  • Generators and promises preserve a sequential-looking flow while asynchronous tasks run, but require coordinating promise settlement with generator resumption. section 6.4

How Secrets of the JavaScript Ninja, Second Edition covers it

How deep it goes
Explains callback drawbacks and generator-promise suspension and resumption, without detailing promise internals.
Examples
Uses dependent ninja, mission, and mission-details JSON requests to compare synchronous, callback, and generator-promise code.
What it assumes
Introduces generator syntax before combining it with promises, rather than assuming familiarity with function* or yield.
What you can do after
Understand how generators and promises coordinate dependent asynchronous tasks without blocking the UI.
How it connects
Connects asynchronous programming with callbacks, generators, promises, and browser UI responsiveness.

Also explained in

Compare how 28 books explain asynchronous programming →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Secrets of the JavaScript Ninja, Second Edition. The section links point to the parts of the book it draws on.