乐趣区

关于前端:BFEdev前端刷题32-实现Promiseall

bfe.dev 是一个针对前端的刷题网站,像是前端的 LeetCode。该系列文章是我在下面的刷题日记。

题目 32

BFE.dev#32 实现Promise.all()

剖析

Promise.all()返回一个 Promise,其

  1. 当所有的 promise fulfill 的时候 fulfill
  2. 当任意一个 promise reject 的时候 reject

显然咱们能够给所有的 promise 增加新的 handler,

  1. fulfill handler: 保留失去的数据,当检测到所有 promise 都曾经 resolve 的时候 resolve 最终返回的 promise
  2. 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…

心愿能有所帮忙,下次再见!前端刷题!走起!

退出移动版