在面试中,手写promise.all方法是很常见的,我也对这一部分知识点掌握的不够牢固,现在就写一篇文章,来好好复盘一下这一部分的手写该如何去写
首先还是要看一下MDN中对Promise.all方法的定义:
可以看到,all方法接受一个可迭代对象作为输入,并返回一个promise,什么是可迭代对象呢
可迭代对象就是一种支持迭代操作的数据结构,我们可以简单认为支持for...of 循环来遍历对象中的元素的就是可迭代对象,例如:
1.数组(Array) 2.字符串(string) 3.集合(Set) 4.映射(Map)
这也就是为什么,我们在手写all方法时,不能使用length和size来判断传入对象的数量,所以要使用for...of搭配count变量来实现,这也是其中比较难记忆的一点。
下面直接展示代码内容吧
Promise.myAll = function (fn) {
let res, rej
const p = new Promise((resolve, reject) => {
res = resolve
rej = reject
// 通过 count 和 for of 来判断传入 myAll 里 fn 的对象数量
// 官方说法promise.all的输入是一个可迭代对象
// (不能用 length 和 size ,因为如果传入的是 Set 或 Map等就不好判断,但是for of可以用来判断可迭代对象)
let count = 0
const result = []
// 使用i来获取fn里数据的下标
let i = 0
// 定义完成promise的数量
let fulfilledCouont = 0
for (const item of fn) {
const index = i
i++
count++
// 把每一项变成promise
Promise.resolve(item).then((data) => {
// 把运行结果存进result
result[index] = data
fulfilledCouont++
// 若所有promise都已经完成,就返回一个成功的promise
if (fulfilledCouont === count) {
res(result)
}
// 如果有失败的,就直接返回失败promise
}, rej)
}
// 如果传递的是空数组,直接完成
if (count === 0) {
res(result)
}
})
return p
}
const p1 = Promise.resolve(666)
Promise.myAll([1, 2, 3, p1]).then(data => {
console.log(data)
},
err => {
console.log(err)
})
而promise.race方法就较为简单了,在传入race方法的可迭代对象里,只要有一个成功就接受那个成功的结果
代码直接展示
Promise.myRace = function (fn) {
const p = new Promise((resolve, reject) => {
for (const item of fn) {
Promise.resolve(item).then(resolve, reject)
}
})
return p
}