这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
这个系列也没啥花头,就是来整平时面试的一些手写函数,考这些简单实现的好处是能看出基本编码水平,且占用时间不长,更全面地看出你的代码实力如何。一般不会出有很多边界条件的问题,那样面试时间不够用,考察不全面。
平时被考到的 api 如果不知道或不清楚,直接问面试官就行, api 怎么用这些 Google 下谁都能马上了解的知识也看不出水平。关键是在实现过程,和你的编码状态、习惯、思路清晰程度等。
注意是简单实现,不是完整实现,重要的是概念清晰和实现思路清晰,建议
先解释清楚概念
=>写用例
=>写伪代码
=>再实现具体功能
,再优化
,一步步来。
27. Promise.all
问题是什么
我们上一篇提到了一个Promise的 api Promise.all
, 现在我们实现它试试
回顾下下 Promise.all()
的用处
- 接收一个可迭代的对象,例如Array,其中每个成员理论上都应该是Promise,数组中如有非Promise项,则此项当做成功
- 如果所有Promise都成功,则返回成功结果数组
- 如果有一个Promise失败,则返回这个失败结果
再来个测试用例就很清楚了
// 声明各种写法的 promise 异步函数
const pro1 = Promise.resolve('第1个 Promise (直接 resolve 的)')
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('第2个 Promise (包裹返回)')
}, 2000)
})
const pro3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, '第3个 Promise(带参数)')
})
const pro4 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('第4个 Promise 失败')
}, 4000)
})
// 再来一个非Promise项 直接 number 100
const proPrimite = 100
// 都是成功的情况
const proAll = Promise.all([pro1, pro2, proPrimite, pro3]).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
// [ '第1个 Promise (直接 resolve 的)',
// '第2个 Promise (包裹返回)',
// 100,
// '第3个 Promise(带参数)' ]
// 有失败的情况
const proAll2 = Promise.all([pro1, pro4, proPrimite]).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
// 第4个 Promise 失败
当然你要是想优雅点,写个工厂来创建 promise,像上篇一样, 也行。
分析
明白了这个函数是做什么的,那么我们思考如何去实现它
首先要实现个函数,你要先清楚它的出入参,上面的例子很容易看出
Promise.all([pro1, pro4, proPrimite]).then(res => {}).catch(e => {})
我们观察到使用 Promise.all
时,用 then
,表明它返回值是个 Promise
而入参是 接收一个可迭代的对象
,例如Array
我们可以写出基本架子
const myPromiseAll = (iterableArr) => {
return new Promise((resolve, reject) => {
// ...
})
}
稍微做点鲁棒性,别啥参数都往里面传
const myPromiseAll = (iterableArr) => {
return new Promise((resolve, reject) => {
if (!Array.isArray(iterableArr)) {
return reject(new Error('params is not an iterable Array'))
}
})
}
下面我们还有的线索是
- 都成功返回成功结果数组
- 有失败则返回这个失败结果
注意:这个的resolve
回调执行是在所有输入的 promise 的 resolve 回调都结束
,或者输入的iterableArr
里没有promise
了的时候。
所以我们需要创建一个结果数组
来保存所有成功的 resolve 回调的结果, 并创建一个计数器来判断是否还有迭代元素, 然后就简单了 遍历数组执行回调,保存输出,看代码注释就行
const myPromiseAll = (iterableArr) => {
return new Promise((resolve, reject) => {
if (!Array.isArray(iterableArr)) {
return reject(new Error('params is not an iterator Array'))
}
// 我们可以创建一个结果数组来保存所有成功的 resolve 回调的结果
let res = [], count = 0
// 开始遍历每个迭代元素
for (let i = 0; i < iterableArr.length; i++) {
// 最上面第一个例子可以看出 直接Promise.resolve() 可传入基本类型
Promise.resolve(iterableArr[i]).then(value => {
// 成功resolve 回调的结果 推入 res 基本类型直接推入 res
res.push(value)
count++
// 当所有resolve回调 都结束,Promise.all的这个 resolve 才会执行
if (count === iterableArr.length) {
resolve(res)
}
}).catch(e => {
// 有错就直接 reject 了
reject(e)
})
}
})
}
最后我们可以替换上面例子中的 Promise.all 尝试也能输出正确结果
const proAll = myPromiseAll([pro1, pro2, proPrimite, pro3]).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
另外向大家着重推荐下另一个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列 记得点赞哈
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧