Skip to content

Instantly share code, notes, and snippets.

@jonurry
Created March 22, 2018 12:03
Show Gist options
  • Save jonurry/11a8a51c273f94b2a1e4fe24134800e9 to your computer and use it in GitHub Desktop.
Save jonurry/11a8a51c273f94b2a1e4fe24134800e9 to your computer and use it in GitHub Desktop.
11.2 Building Promise.all() (Eloquent JavaScript Solutions)
function Promise_all(promises) {
return new Promise((resolve, reject) => {
let results = [];
try {
for (let i=0; i<promises.length; i++) {
let last = (i === promises.length - 1);
promises[i].then(value => {
results[i] = value;
if (last) resolve(results);
}).catch(reject);
}
if (promises.length === 0) resolve(results);
} catch (e) {
reject;
}
});
}
// Test code.
Promise_all([]).then(array => {
console.log("This should be []:", array);
});
function soon(val) {
return new Promise(resolve => {
setTimeout(() => resolve(val), Math.random() * 500);
});
}
Promise_all([soon(1), soon(2), soon(3)]).then(array => {
console.log("This should be [1, 2, 3]:", array);
});
Promise_all([soon(1), Promise.reject("X"), soon(3)])
.then(array => {
console.log("We should not get here");
})
.catch(error => {
if (error != "X") {
console.log("Unexpected failure:", error);
}
});
@jonurry
Copy link
Author

jonurry commented Mar 22, 2018

11.2 Building Promise.all()

Given an array of promises, Promise.all returns a promise that waits for all of the promises in the array to finish. It then succeeds, yielding an array of result values. If any of the promises in the array fail, the promise returned by all fails too, with the failure value from the failing promise.

Implement something like this yourself as a regular function called Promise_all.

Remember that after a promise has succeeded or failed, it can’t succeed or fail again, and further calls to the functions that resolve it are ignored. This can simplify the way you handle failure of your promise.

@jonurry
Copy link
Author

jonurry commented Mar 22, 2018

Hints

The function passed to the Promise constructor will have to call then on each of the promises in the given array. When one of them succeeds, two things need to happen. The resulting value needs to be stored in the correct position of a result array, and we must check whether this was the last pending promise and finish our own promise if it was.

The latter can be done with a counter which is initialized to the length of the input array and from which we subtract 1 every time a promise succeeds. When it reaches 0, we are done. Make sure you take the situation where the input array is empty (and thus no promise will ever resolve) into account.

Handling failure requires some thought but turns out to be extremely simple. Just pass the reject function of the wrapping promise to each of the promises in the array as a catch handler or as second argument to then so that a failure in one of them triggers the rejection of the whole wrapper promise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment