bfe.dev 是一个针对前端的刷题网站,像是前端的 LeetCode。该系列文章是我在下面的刷题日记。
题目 32
BFE.dev#32 实现Promise.all()
剖析
Promise.all()
返回一个 Promise,其
- 当所有的 promise fulfill 的时候 fulfill
- 当任意一个 promise reject 的时候 reject
显然咱们能够给所有的 promise 增加新的 handler,
- fulfill handler: 保留失去的数据,当检测到所有 promise 都曾经 resolve 的时候 resolve 最终返回的 promise
- rejected handler: 立马 reject 最终返回的 promise
开始写代码吧
首先,骨架代码如下,很容易了解
function all(promises) {return new Promise((resolve, reject) => {promises.forEach((promise, index) => {promise.then((value) => {// TODO}, (error) => {// TODO})
})
})
}
fulfill 的 data 须要存在一个数组里,然而 promise 的 fulfill 机会未知,先后顺序不定,所以不能 push,而是利用 index 来搁置数据到正确的地位。
这样做过后,存放数据的数组就不能通过 length 来判断是否所有的 proimse 都曾经 fulfill 了,所以用另外一个变量来计数。
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})
})
})
}
解决 rejection 的时候比较简单,间接 reject 最初返回的 promise 即可。然而要留神 reject 过后,仍然可能有 promise 持续 fulfill 或者 reject,咱们须要疏忽这些状况,所以用一个 isErrored
的 flag 即可。
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)
})
})
})
}
最初一部分就是对于输出解决的,因为 Promise.all 反对传入非 Promise 数据,所以在代码的一开始,咱们将非 Promise 数据包装一下即可。最终失去如下代码!
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)
})
})
})
}
通过撒花!????
如果你感兴趣,能够在 BFE.dev 上试试 https://bigfrontend.dev/zh/pr…
心愿能有所帮忙,下次再见!前端刷题!走起!