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