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...

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