A Promise represents work that finishes later. It wraps a value or long-running operation, then makes its eventual result or failure available without nesting callback after callback. section 8.2
A Promise starts as pending and becomes settled when it is fulfilled or rejected. Fulfillment calls the resolve path; rejection calls the reject path. The then method chains transformations in a mostly linear flow, while catch centralizes error handling. section 8.2
Promises make asynchronous programs easier to compose by:
- Flattening nested callbacks into chained steps. section 8.2
- Making temporal coupling—the need to wait for data—explicit. section 8.2
- Consolidating failures instead of repeating error callbacks. section 8.2
- Supporting both sequential chains and concurrent work with Promise.all(). section 8.2
Wrapping an asynchronous request
const getJSON = url => new Promise((resolve, reject) => { const req = new XMLHttpRequest(); req.responseType = 'json'; req.open('GET', url); req.onload = () => req.status === 200 ? resolve(JSON.parse(req.responseText)) : reject(new Error(req.statusText)); req.onerror = () => reject(new Error('IO Error')); req.send(); }); getJSON('/students').then( students => console.log(students), error => console.log(error.message) ); section 8.2
Sequential versus concurrent requests
A chain can fetch each student's grades one after another, but that creates a waterfall. Mapping grade URLs and passing them to Promise.all() starts several requests together, after which the results can be transformed and handled through one catch path. section 8.2
Figure 8.5. How an async operation is wrapped in a Promise and provided with two callbacks: one for resolve and another for reject. The promise begins with a status of pending and then is either fulfilled or rejected, invoking the function resolve or reject, respectively, before moving into the settled state.
Track the Promise lifecycle from pending through fulfillment or rejection, including the resolve and reject callbacks. section 8.2






