专栏首页BFE.dev前端刷题日记BFE.dev前端刷题#32. 实现`Promise.all()`
原创

BFE.dev前端刷题#32. 实现`Promise.all()`

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/problem/implement-Promise-all

希望能有所帮助,下次再见! 前端刷题!走起!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • BFE.dev前端刷题 33. 实现Promise.allSettled()

    和Promise.all()不同,Promise.allSettled()即使是遇到rejection也会等待所有的promise到最后。所以我们只需要用一个a...

    JSer
  • 如何检测JavaScript中的死循环?

    如果我们需要执行用户写的代码,如和避免死循环?我们最近遇到了这个问题,因为写错代码很常见,所以我们进行了一下尝试。

    JSer
  • BFE.dev前端刷题1 - 实现curry()

    也就是说 curry() 需要返回一个function,这个function接受任意数量的参数,并且

    JSer
  • 今日一题 - 请模拟实现一个Promise.all() 方法?

    Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

    zz_jesse
  • 雅虎军规第三天

    页面含有重复的脚本文件会影响性能,因为重复脚本会创建不必要的HTTP请求,执行无用的JavaScript代码,而影响页面性能。即使脚本是可缓存的,在用户重新加载...

    wade
  • PostgreSQL 常用SQL语句

    PostgreSQL 可以说是目前功能最强大、特性最丰富和结构最复杂的开源数据库管理系统,其中有些特性甚至连商业数据库都不具备。这个起源于加州大学伯克利分校的数...

    YP小站
  • 管理者,别总以为自己比员工聪明

    创业公司,老板对技术团队不满意,故空降来了一个职业经理人CTO来带队,并提了明确的要求,“必须要让不懂技术的人,看懂管理结果”,更具体的:要量化,要体系化,要有...

    架构师之路
  • LeetCode 1161. 最大层内元素和(层序遍历)

    给你一个二叉树的根节点 root。设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推。

    Michael阿明
  • 推荐算法设计综述

    http://www.tensorinfinity.com/paper_178.html

    SIGAI学习与实践平台
  • 《spss统计分析与行业应用案例详解》:实例十五 两个关联样本检验

    分析一种新药,选取15名患者,是沿着服药前后的血红蛋白数量,分析该药时候引起患者血红蛋白数量显著变化

    统计学家

扫码关注云+社区

领取腾讯云代金券