While the race metaphor may not be meant to be taken literally, it can be understood in the following way:
- Think of the runner as an asynchronous process (such as fetching a document from a web server or database, awaiting user input, or simply waiting for time to pass).
- The promise acts as a time-keeper that notifies when the runner crosses the finish line (when the document or user input is available, or when the designated time has elapsed).
- The winner of the race is determined by the first time-keeper that announces the result (also known as the winning time).
Even after one race is won, other time-takers (aside from the one declaring the victory) must still monitor their runners1, as they might be participating in another race where they could emerge victorious. An example is provided below.
var over;
function runner(ms) {
return new Promise(function timetaker(resolve, reject) {
setTimeout(function() {
if (!over) resolve(`Finished after ${ms} ms`);
}, ms);
});
}
function endofrace(result) {
console.log(result);
//over = true;
}
var veryslow = runner(2000);
var slow = runner(1000);
var fast = runner(500);
Promise.race([slow, fast]).then(endofrace);
Promise.race([slow, veryslow]).then(endofrace);
To prevent certain behaviors ("disqualifying losers from other races"), you need to implement "race-is-over" awareness into the promise, similar to the over
variable in the example. By uncommenting the specified line, the racer with a duration of 1000 ms will no longer have a chance to win the second race.
(Specifically, if over = true
, the runner's setTimeout
will still complete, but the time-keeper will cease reporting further results. The awareness of the race being over lies with the time-keeper, not the runner. Alternatively, in the context of a web server request, the race-is-over awareness could reside with the runner to abort the request once the race concludes.)
1 Another limitation of the metaphor: It is inaccurate to assume that time-takers (promises) consume resources while observing the runners.