一、promise.all
传的是一个数组, 返回一个promise对象, 如果执行的promise都成功的话 返回 成功的结果数组 否则 返回失败的结果
function PromiseAll(pArr) {
if (!Array.isArray(pArr)) {
return `请传入一个数组`;
}
// 返回一个Promise对象
return new Promise((resolve, reject) => {
// 用于存储全部成功的结果
let res = [];
// 当前promise执行数
let count = 0;
for (let i = 0; i < pArr.length; i++) {
// 防止传入数字或字符串的情况
Promise.resolve(pArr[i])
.then((r) => {
// 若成功的count+1
count++
// res[i]为当前promise处理后的结果, 注意这里不能用push 否则不能对应到当前的promise
res[i] = r
// 如果count 等于 promise全部的长度
if(count === pArr.length) {
resolve(res)
}
})
.catch((err) => {
reject(err)
});
}
});
}
二、promiseAllSettle
传的是一个数组, 返回一个promise对象, 无论成功或失败都向数组里存入当前的值 例如:{status: fulffilled, value: '123'}, 和promise.All类似
function promiseAllSettle(pArr) {
if(!Array.isArray(pArr)) {
return `传入的参数必须是数组`
}
return new Promise((resolve, reject) => {
let count = 0
let res = []
for(let i = 0;i < pArr.length;i++) {
Promise.resolve(pArr[i]).then(r => {
res[i] = {
// 成功状态
status: 'fullfilled',
value: r
}
count++
}).catch(err => {
res[i] = {
// 失败状态
status: 'rejected',
value: err
}
count++
}).finally(() => {
// 如果执行完了 返回结果
if(count === pArr.length) {
resolve(res)
}
})
}
})
}
let p1 = new Promise((resolve, reject) => {
resolve('p1')
})
let p2 = new Promise((resolve, reject) => {
reject('p2')
})
let p3 = new Promise((resolve, reject) => {
reject(`p3`)
})
let pArr = [p1, p2, p3]
let arr = promiseAllSettle(pArr)
三、promiseFinally
Promise.prototype.promiseFinally = function(cb) {
return this.then((value) => {
// 执行一次传入的回调函数 在返回原始的promise值
return Promise.resolve(cb()).then(() => {
return value
})
}, (err) => {
return Promise.resolve(cb()).then(() => {
throw err
})
})
}
let p = new Promise((resolve, reject) => {
reject(`error1`)
}).promiseFinally(() => {
console.log(123)
})
console.log(p)
四、promise并发
// 定义url数组
const urls = [{
info: 'link1',
time: 3000
}, {
info: 'link2',
time: 2500
}, {
info: 'link3',
time: 1600
}, {
info: 'link4',
time: 1000
}, {
info: 'link5',
time: 2000
}]
// 解析url返回promise
function loadImg(url) {
return new Promise((resolve, reject) => {
console.log(`---start`, url.info)
setTimeout(() => {
resolve(url.info)
console.log('---end', url.info)
}, url.time)
})
}
class PromiseQueue {
constructor(options = {}) {
// 最大并发数量
this.concurreny = options.concurreny || 3
// 当前并发数量
this.concurrent = 0
// 存储任务数组
this.pendingList = []
}
add(task) {
// 向数组推动任务
this.pendingList.push(task)
// 执行任务
this.run()
}
run() {
// 如果当前并发数量大于等于最大并发数量, 就不往下执行了 比如最大并发数量为3 就是 0 1 2 进任务 到3了停止
// 等0 1 2 其中一个结束了 此时concurrent = 2 满足条件 在执行下一个任务
if(this.concurrent >= this.concurreny || this.pendingList.length === 0) {
return
}
// 使当前并发数+1
this.concurrent++
// 取出
let {fn} = this.pendingList.shift()
fn().then(res => {
this.concurrent--
this.run()
})
}
}
const p1 = new PromiseQueue()
urls.forEach(item => {
p1.add({
fn: () => loadImg(item),
})
})
let HighTask = {
info: 'link111',
time: 3000
}
p1.add({
fn: () => loadImg(HighTask),
})