As far as I know, there are two options about promise:
promise.all()
promise.race()
Ok, I know what promise.all()<
It's a piece to build a timeout system, where:
For an example of the second, one might show a spinner "instantly" while still defaulting to show real content if it comes in fast enough. Try running the below a few times - note at least some console message comes "instantly". This might normally be attached to perform operations on a UI.
The key to note is - the result of Promise.race
is much less important than the side effects (though, this then is a code smell).
// 300 ms _feels_ "instant", and flickers are bad
function getUserInfo(user) {
return new Promise((resolve, reject) => {
// had it at 1500 to be more true-to-life, but 900 is better for testing
setTimeout(() => resolve("user data!"), Math.floor(900*Math.random()));
});
}
function showUserInfo(user) {
return getUserInfo().then(info => {
console.log("user info:", info);
return true;
});
}
function showSpinner() {
console.log("please wait...")
}
function timeout(delay, result) {
return new Promise(resolve => {
setTimeout(() => resolve(result), delay);
});
}
Promise.race([showUserInfo(), timeout(300)]).then(displayed => {
if (!displayed) showSpinner();
});
Inspiration credit to a comment by captainkovalsky.
An example of the first:
function timeout(delay) {
let cancel;
const wait = new Promise(resolve => {
const timer = setTimeout(() => resolve(false), delay);
cancel = () => {
clearTimeout(timer);
resolve(true);
};
});
wait.cancel = cancel;
return wait;
}
function doWork() {
const workFactor = Math.floor(600*Math.random());
const work = timeout(workFactor);
const result = work.then(canceled => {
if (canceled)
console.log('Work canceled');
else
console.log('Work done in', workFactor, 'ms');
return !canceled;
});
result.cancel = work.cancel;
return result;
}
function attemptWork() {
const work = doWork();
return Promise.race([work, timeout(300)])
.then(done => {
if (!done)
work.cancel();
return (done ? 'Work complete!' : 'I gave up');
});
}
attemptWork().then(console.log);
You can see from this one that the timeout's console.log
is never executed when the timeout hits first. It should fail/succeed about half/half, for testing convenience.