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



























