I am trying to implement my own Promise.all
to prepare my interviews.
My first version is this
Promise.all = function(promiseArray) {
return new Promise((resolve, reject) => {
try {
let resultArray = []
const length = promiseArray.length
for (let i = 0; i <length; i++) {
promiseArray[i].then(data => {
resultArray.push(data)
if (resultArray.length === length) {
resolve(resultArray)
}
}, reject)
}
}
catch(e) {
reject(e)
}
})
}
However, the native Promise.all
accepts not just arrays, but also any iterables, which means any object that has Symbol.iterator
, such as an array or a Set or Map.
So something like this is going to work with the native Promise.all
but not with my current implementation
function resolveTimeout(value, delay) {
return new Promise((resolve) => setTimeout(resolve, delay, value))
}
const requests = new Map()
requests.set('reqA', resolveTimeout(['potatoes', 'tomatoes'], 1000))
requests.set('reqB', resolveTimeout(['oranges', 'apples'], 100))
Promise.all(requests.values()).then(console.log); // it works
I modified my Promise.all
by first adding a check to see if it has Symbol.iterator
to make sure it is an iterable.
Promise.all = function(promiseArray) {
if (!promiseArray[Symbol.iterator]) {
throw new TypeError('The arguments should be an iterable!')
}
return new Promise((resolve, reject) => {
try {
But the challenge is with how to iterate through the iterable. Current implementation is to get the length of if and doing it with a for loop via const length = promiseArray.length
however only arrays have length
property on it, other iterables or iterators like Set
or Map.values()
will not have that property available.
How can I tweak my implementation to support other types of iterables like the native Promise.all
does