面试官要求我们手动实现 Promise.all

情景:

最近面试,有两次被问到手动实现 Promise.all,不幸的是我都没把这题做好。因为我没有去准备这个,我不知道手动实现已有的 API 有什么意义。

但是为了防止以后还会遇到此类题,还是记录下吧,同时也是为了给同样遇到该面试题坑的同学一点微不足道的帮助。

难点:

其实这道题并没有什么难度,难点在于你如果之前没有思考过类似手动实现异步任务的并发处理时,很难捅破如何确定这几个任务都已经执行完了,并且已经拿到了全部该有的数据这层窗户纸,容易转不过来弯儿。

思路:

因为 Promise 是个异步任务,在数据没返回之前它相当于是动态的,我们要确定任务是否都已经成功执行完毕并且拿到了数据,就需要找一个静止的、我们能够掌控的东西,那就是 .then 后面的回调函数。

我们可以设置一个数组,用它来存放每个 Promise 返回的数据,当该数组的长度等于 Promise 任务的个数时,说明拿到了所有的数据,此时就可以把该数组返回出去了。

然后又因为原生 Promise.all 返回的是一个 Promise,所以我们也需要返回一个 Promise,然后把结果数据放入 resolve 中返回出去。

代码:

Promise.all = promises => {
    // 返回的是一个 Promise
    return new Promise((resolve, reject) => {
        let dataArr = []

        for (let p of promises) {
            // 在 .then 中收集数据,并添加 .catch,在某一个 Promise 遇到错误随时 reject。
            // 这样,在最外面调用 Promise.all().catch() 时也可以 catch 错误信息
            p.then(addData).catch(reject)
        }

        function addData(data) {
            dataArr.push(data)
            // 如果数据收集完了,就把收集的数据 resolve 出去
            if (dataArr.length === promises.length) resolve(dataArr)
        }
    })
}

测试用例1:

let p1 = new Promise(resolve => { resolve('p1') })
let p2 = new Promise(resolve => { resolve('p2') })
let p3 = new Promise(resolve => { resolve('p3') })
let p4 = new Promise(resolve => { resolve('p4') })
let p5 = new Promise(resolve => { resolve('p5') })

Promise.all([p1, p2, p3, p4, p5]).then(res => {
    console.log(res)
}).catch(err => {
    console.error(err)
})

测试用例2:

let p1 = new Promise(resolve => { resolve('p1') })
let p2 = new Promise(resolve => { resolve('p2') })
let p3 = new Promise((resolve, reject) => { reject('p3') })
let p4 = new Promise(resolve => { resolve('p4') })
let p5 = new Promise(resolve => { resolve('p5') })

Promise.all([p1, p2, p3, p4, p5]).then(res => {
    console.log(res)
}).catch(err => {
    console.error(err)
})

原文链接:juejin.im

上一篇:ThreeJS —— 机房Demo(一)
下一篇:父组件利用事件总线向子组件通信,子组件没有响应是怎么回事

相关推荐

  • 🔥《吊打面试官》系列 Node.js 必知必会必问!

    (/public/upload/f204a3b224d986128f1b4d9b8d06cd17) 前言 codeing 应当是一生的事业,而不仅仅是 30 岁的青春🍚 本文已收录 Git...

    5 个月前
  • 🔥 Promise|async|Generator 实现&原理大解析 | 9k字

    笔者刚接触async/await时,就被其暂停执行的特性吸引了,心想在没有原生API支持的情况下,await居然能挂起当前方法,实现暂停执行,我感到十分好奇。好奇心驱使我一层一层剥开有关JS异步编程的...

    5 个月前
  • 面试题1:Promise递归实现拉取数据

    题目:请用promise递归实现拉取100条数据,每次拉取20条,结束条件为当次拉取不足20条或者已经拉取100条数据 ...

    3 个月前
  • 面试官:谈谈你对 CSS 盒模型的认识?(你确定会?)

    题目:谈谈你对 CSS 盒模型的认识 涉及知识点(层层递进): 1. 基本概念:标准模型 IE模型(区别) 2. CSS如何设置这两种模型 3. JS如何设置获取盒子模型对应的宽和高 4....

    2 年前
  • 面试官:请手写一个webpack4.0配置

    确认过眼神,你还是没有准备秋招的人?时间仓促。自京东6月8号开启管培生的招聘,就意味着秋招的开始。然而你还在等着秋天的到来?今年形势应该更为严峻,随着各大技术(vue,webpack,react,微信...

    2 年前
  • 面试官:请你在React中引入Vue3的@vue/reactivity,实现响应式。

    前言 React的状态管理是一个缤纷繁杂的大世界,光我知道的就不下数十种,其中有最出名immutable阵营的redux,有mutable阵营的mobx,reacteasystate,在hooks诞生...

    6 个月前
  • 面试官:请你介绍一下let const Object.freeze() ,set和get

    image.png(https://img.javascriptcn.com/a14365703d60277d0d01bfbcacf51841 "image.png") 前端巅峰 每日一题 : ...

    9 个月前
  • 面试官:说说执行上下文吧

    当 JS 引擎处理一段脚本内容的时候,它是以怎样的顺序解析和执行的?脚本中的那些变量是何时被定义的?它们之间错综复杂的访问关系又是怎样创建和链接的?要解释这些问题,就必须了解 JS 执行上下文的概念...

    3 个月前
  • 面试官:说说原型链和继承吧

    JavaScript 中没有类的概念的,主要通过原型链来实现继承。通常情况下,继承意味着复制操作,然而 JavaScript 默认并不会复制对象的属性,相反,JavaScript 只是在两个对象之间创...

    3 个月前
  • 面试官:说说作用域和闭包吧

    几乎所有语言的最基础模型之一就是在变量中存储值,并且在稍后取出或修改这些值。在变量中存储值和取出值的能力,给程序赋予了状态。这就引伸出两个问题:这些变量被存储在哪里?程序如何在需要的时候找到它们?回...

    3 个月前

官方社区

扫码加入 JavaScript 社区