What if a request starts now, but the screen needs its data later? A promise is an object representing a value that will become available. Call .then() with a callback to use that value. If the promise is pending, the callback waits; if it has already resolved, the callback still runs, but is scheduled rather than invoked immediately. section 30.0
Load organizations
axios.get(url).then(resp => { const orgs = resp.data; }); First, axios.get starts an AJAX request and returns a promise. When the request succeeds, the callback receives the response. A view can keep that promise when it starts loading, then attach .then() when it is ready to display the organizations. section 30.1
Requests can fail. Supply a second callback to .then(success, error) to handle rejection. For longer sequences, .catch(errorHandler) is shorthand for .then(null, errorHandler); each .then() or .catch() returns a new promise, forming a chain. section 30.2 section 31.4
Promise helpers keep the same promise-based interface across different situations:
- Promise.resolve(value) supplies an already available value as a resolved promise; Promise.reject(reason) creates a rejected one. section 30.3
- Promise.all(array) waits for all the promises to resolve; Promise.race(array) waits for the first to resolve. section 30.4
const transactions = {};
getTransaction(id) {
if (transactions[id]) {
return Promise.resolve(transactions[id]); 1
} else {
const loading = load(`/transactions/${id}`); 2
loading.then(transaction => {
transactions[id] = transaction; 3
});
return loading; 4
}
}
getTransaction(405).then(transaction => {
// do something with transaction
}, err => { 5
// handle error
})
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":4,\"ch\":55},{\"line\":4,\"ch\":56}],[{\"line\":6,\"ch\":55},{\"line\":6,\"ch\":56}],[{\"line\":8,\"ch\":55},{\"line\":8,\"ch\":56}],[{\"line\":10,\"ch\":55},{\"line\":10,\"ch\":56}],[{\"line\":14,\"ch\":15},{\"line\":14,\"ch\":16}],[{\"line\":14,\"ch\":17},{\"line\":14,\"ch\":18}],[{\"line\":16,\"ch\":55},{\"line\":16,\"ch\":56}]]"}
!@%STYLE%@!
Follow both paths through getTransaction: a cache hit returns Promise.resolve(cachedValue), while a miss returns the loading promise. Either way, the caller uses .then() and can provide an error handler. section 30.3
Make a promise from a callback
To wrap image loading, return new Promise((resolve, reject) => { /* start loading */ }). Connect the image's onload handler to resolve and its onerror handler to reject. The returned promise now represents the outcome of that load, so callers can handle success or failure with .then(). section 31.1
function fade(image) {
return new Promise(resolve => { 1
function fadeIn(alpha) { 2
draw(image, alpha); 3
if (alpha >= .99) {
resolve(); 4
} else {
alpha += (1-alpha)/24; 5
window.requestAnimationFrame(() => fadeIn(alpha)); 5
}
}
fadeIn(0.1); 6
});
}
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":1,\"ch\":62},{\"line\":1,\"ch\":63}],[{\"line\":7,\"ch\":18},{\"line\":7,\"ch\":19}],[{\"line\":11,\"ch\":13},{\"line\":11,\"ch\":14}],[{\"line\":2,\"ch\":62},{\"line\":2,\"ch\":63}],[{\"line\":7,\"ch\":27},{\"line\":7,\"ch\":28}],[{\"line\":3,\"ch\":62},{\"line\":3,\"ch\":63}],[{\"line\":5,\"ch\":62},{\"line\":5,\"ch\":63}],[{\"line\":7,\"ch\":28},{\"line\":7,\"ch\":29}],[{\"line\":7,\"ch\":62},{\"line\":7,\"ch\":63}],[{\"line\":8,\"ch\":62},{\"line\":8,\"ch\":63}],[{\"line\":7,\"ch\":62},{\"line\":7,\"ch\":63}],[{\"line\":8,\"ch\":62},{\"line\":8,\"ch\":63}],[{\"line\":11,\"ch\":62},{\"line\":11,\"ch\":63}]]"}
!@%STYLE%@!
A canvas fade returns a promise that resolves only when its animation reaches the finishing opacity. This makes completion of an animation usable like completion of a request. section 34.2
Try combining three requests: wait for a credit-availability request and whichever of two credit-score requests finishes first. Which helper should combine the scores, and which should combine that result with credit availability? section 30.4






