Good job using const
for values
, as well as let
for re-assignable values like counter
and rejected
.
Did you test this code? My presumption is that it didn't happen, because when I tried running it, I see the following error:
error promise.then is not a function
This is because the promises are spread out:
function all (...promises) {
Without the spread operator it appears to run as I would expect, as long as each entry in promises
is a promise.
I must admit I compared with another implementation of Promise.all()
. In comparison with that function, yours tracks rejected
, whereas the other one simply calls reject
whenever a promise is rejected.
Another thing I noticed is that the variable name promise
is reused - both for the outer promise to be returned by all()
as well as the callback to promises.forEach()
. It would be wise to use different names to improve readability. In fact there is little need to assign the outer promise - it can simply be returned without being assigned to a variable since it isn't modified after being instantiated.
Another aspect to consider is that Promise.all()
can accept promises or non-promises - e.g. the MDN documentation gives an example like this:
const promise1 = Promise.resolve(3);
const promise2 = 42; // <- not really a promise
const promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
}).catch(error => {
console.log('error: ', error.message);
});
// expected output: Array [3, 42, "foo"]
With your code, it throws the error promise.then is not a function
so it might be wise to check if each item is a promise before calling .then()
on it.
resolve()
and notfulfill()
in the first place. \$\endgroup\$