Promise.all
手写
// 使用es6新增的全局对象Reflect的静态函数式方法去给Promise构造函数增加'myAll'方法
//用法基本和Object.defindeProperty类似,value对应的就是我们myAll的函数主体
Reflect.defineProperty(Promise, 'myAll', {
value: (array) => {
const results = new Array(); // 创建一个数组接收结果
let count = 0; // 创建一个计数器,原因在下面阐述
return new Promise((res, rej) => { // 因为Promise.all返回的也是一个Promise实例,所以要return一个Promise实例
array.forEach(async (item, index) => { // 遍历数组
try {
results[index] = await item;
// 把数组中的每一个元素都放到对应index的results中,这里用await并不只是用es6装逼,而是考虑到元素可能不是promise实例,用await可以将普通元素转换为状态是fulfilled的promise再提取PromiseResult,这样就不用分类讨论这个元素的类型是不是promise了。
} catch (res) {
rej(res) //捕获错误
}
count++ // 每存入一个元素,计数器就加一
if (array.length === count) res(results) // 如果每一个元素都放入了results中,即数组长度和计数器数相等,则返回状态为fulfilled参数为results的promise
})
})
}
})
测试用例
const a = new Promise((resolve) => { resolve(1) })
const b = new Promise((res) => {
setTimeout(() => { res(2) }, 2000)
})
const c = new Promise((res) => {
setTimeout(() => { res(3) }, 1000)
})
function d() {
return new Promise((res, rej) => { rej('可能是网络的问题,请求失败') })
}
输出结果
Promise.myAll([a, b, c, 4, 5, null, undefined]).then((res) => { console.log(res) }).catch((reason) => console.log(reason))
// [1, 2, 3, 4, 5, null, undefined]
Promise.myAll([a, b, c, d(), 4, 5, null, undefined]).then((res) => { console.log(res) }).catch((reason) => console.log(reason))
// 可能是网络的问题,请求失败