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…
心愿能有所帮忙,下次再见! 前端刷题!走起!
发表回复