1.你了解Promise吗?平时用的多吗?
2.Promise.all你知道有什么特性吗?
- 参数:
Promise.all接收一个数组,数组成员项不仅可以是Promise,也可以是常量等 - 执行情况:
数组中所有Promise执行完成后才会返回结果,
如果其中一个Promise执行报错了,整个Promise.all会执行catch,
但是不影响后面的Promise执行,因为Promise的执行是在其实例化的时候就执行了,利
用这一特性,我们可以做promise的缓存(ES7装饰器)// 装饰器 const cacheMap = new Map() function enableCache(target, name, descriptor) { const val = descriptor.value descriptor.value = async function (...args) { const cacheKey = name + JSON.stringify(args) if (!cacheMap.get(cacheKey)) { const cacheValue=Promise.resolve(val.apply(this,args)).catch(_=>{ cacheMap.set(cacheKey,cacheValue) }) } return cacheMap.get(cacheKey) } return descriptor } class PromiseClass{ @enableCache static async getInfo(){} } PromiseClass.getInfo() PromiseClass.getInfo() PromiseClass.getInfo() PromiseClass.getInfo() PromiseClass.getInfo()
- 返回结果:
返回一个Promise
3.手写Promise.all
function PromiseAll(promiseArray) {
// Promise.all返回的是一个Promise,所以return一个Promise
return new Promise((resolve, reject) => {
// 先判断传入的参数是不是数组
if (!Array.isArray(promiseArray)) {
return reject(new Error('传入的参数必须是数组!'))
}
// 最终的结果数组
const res = []
const promiseLength = promiseArray.length
// 计数器:用于记录执行了几个Promise
let counter = 0
for (let i = 0; i < promiseLength; i++) {
// Promise.resolve()的特性:无论resolve里的参数是什么都会把其转成一个Promise,所以不用判断promiseArray成员项是不是Promise
Promise.resolve(promiseArray[i]).then(value => {
counter++
// 注意:这里不能用数组的push方法
// 原因:
// Promise.all不会改变传入的Promise顺序,但是Promise的执行快慢是不一定的
// 如果使用push,则执行快的Promise会被放到结果数组的前面,这样最终的结果顺序就可能不正确
// res.push(value)
res[i] = value
// 注意:这里的判断条件:只能用counter === promiseLength,不能使用res.length===promiseLength
// 原因:
// 数组的特性:const arr=[],arr[6]='123',此时的arr.length=7,而不是1, 即便是我们只给数组添加了一个下标为6的成员,它也会把前面的空间都留出来的
//
// 注意:判断只能写在.then里,不能写在.then的外面,否则就是同步任务了
if (counter === promiseLength) {
resolve(res)
}
}).catch(e => reject(res))
}
})
}
// 测试
const pro1 = new Promise((res, rej) => {
setTimeout(() => {
res('1')
}, 1000);
})
const pro2 = new Promise((res, rej) => {
setTimeout(() => {
res('2')
}, 2000);
})
const pro3 = new Promise((res, rej) => {
setTimeout(() => {
res('3')
}, 3000);
})
const proAll = PromiseAll([pro1, pro2, pro3])
.then(res => {
console.log(res);//['1','2','3']
}).catch((e) => {
console.log(e);
});