https://bfe.dev is like a LeetCode for FrontEnd developers. I’m using it to practice my skills.
This article is about the coding problem BFE.dev#32. implement Promise.all()
Analysis
Promise.all()
returns a Promise that
- fulfills when all promises have fulfilled
- rejects when any promise is rejected.
So we could chain all the promises with a new fulfill handler and rejection handler:
- when fulfilled, collect the data and check if ready to fulfill the returned Promise
- when rejected, reject the returned Promise.
Let's write some code
Basic skeleton is like this
function all(promises) {
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
promise.then((value) => {
// TODO
}, (error) => {
// TODO
})
})
})
}
The fulfilled data should be stored in an array, and the promises might resolve in different order, so index
is used to set the data at right position.
And the array might have empty holes, so we could use anther variable to keep track of the fulfilled promise count.
function all(promises) {
return new Promise((resolve, reject) => {
const result = []
let fulfilledCount = 0
promises.forEach((promise, index) => {
promise.then((value) => {
result[index] = value
fulfilledCount += 1
if (fulfilledCount === promises.length) {
resolve(result)
}
}, (error) => {
// TODO
})
})
})
}
For rejection, once error happens, latter promises no matter fulfilled or rejected, all should be ignored. we could use a flag to indicate this.
function all(promises) {
return new Promise((resolve, reject) => {
const result = []
let fulfilledCount = 0
let isErrored = false
promises.forEach((promise, index) => {
promise.then((value) => {
if (isErrored) return
result[index] = value
fulfilledCount += 1
if (fulfilledCount === promises.length) {
resolve(result)
}
}, (error) => {
if (isErrored) return
isErrored = true
reject(error)
})
})
})
}
The last part is about the input validation, seems like data types other than Promise could be passed in, so we normalize the input and here is the final code.
function all(promises) {
const _promises = promises.map(
(item) => item instanceof Promise ? item : Promise.resolve(item)
)
// resolve if empty
if (_promises.length === 0) {
return Promise.resolve([])
}
return new Promise((resolve, reject) => {
const result = []
let fulfilledCount = 0
let isErrored = false
_promises.forEach((promise, index) => {
promise.then((value) => {
if (isErrored) return
result[index] = value
fulfilledCount += 1
if (fulfilledCount === _promises.length) {
resolve(result)
}
}, (error) => {
if (isErrored) return
isErrored = true
reject(error)
})
})
})
}
Passed!
If you are interested, have a try at BFE.dev https://bigfrontend.dev/problem/implement-Promise-all
Hope it helps, see you next time!
Top comments (0)