学习文章:https://www.cnblogs.com/longlongdan/p/13962460.html
const promiseOne = new Promise((resolve, reject) => {
resolve(111)
})
const promiseTwo = new Promise((resolve, reject) => {
reject(222)
})
const promiseThree = new Promise((resolve, reject) => {
resolve(333)
})
// 子任务出错,全部就出错
Promise.all([promiseOne, promiseTwo, promiseThree]).then(res => {
console.log(Array.prototype.filter.call(res, Boolean)); //[ 111, 333 ]
}).catch(err => { throw Error("all 出错!") })
// 输出:UnhandledPromiseRejectionWarning: Error: all 出错!
Promise.allSettled([promiseOne, promiseTwo, promiseThree]).then(res => {
console.log(Array.prototype.filter.call(res, Boolean));
return Array.prototype.filter.call(res, Boolean)
}).catch(err => { throw Error("allSettled 出错!") }).finally(() => {
console.log('结束...')
});
/*
[
{ status: 'fulfilled', value: 111 },
{ status: 'rejected', reason: 222 },
{ status: 'fulfilled', value: 333 }
]
结束...
*/
简易并发测试代码
// https://www.cnblogs.com/longlongdan/p/13962460.html
function asyncPools(poolLimit, array, fnInter) { // 并发限制实现: 并发为2
let doing = [];
let i = 0;
let ret = [];
function run() {
if (i >= array.length) {
//最后一个resolve状态,会进入外层返回Promise.then
return Promise.resolve();
}
let e = fnInter(array[i++]);
// e.then(() => doing.splice(doing.indexOf(e), 1))
e.then(() => {
doing.splice(doing.indexOf(e), 1);
}).catch(err => err)
doing.push(e);
ret.push(e);
if (doing.length >= poolLimit) {
// 监听每完成一个就再放一个
// race: 哪个 Promise 对象最快得到结果,就返回那个结果,不管结果本身是成功状态还是失败状态。
return Promise.race(doing).then(run);
} else {
// 改写一下保证then链式调用
return Promise.resolve().then(run);
}
}
// 只有当array结束,最后一个resolve才会进入then
// 注意:这不管是all还是allSettled,子任务失败时都会返回【主要是race函数的作用】
return run().then(() => Promise.all(ret));
// return run().then(() => Promise.allSettled(ret));
}
const moment = require('moment');
// 模拟请求操作
const timeout = i => new Promise((resolve, reject) => {
setTimeout(() => {
// 自定义错误提醒
if (i === 3000) {
// console.log(param, ' failed')
return reject({
status: '请求超时!',
data: i,
date: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
})
}
// console.log(i);
// 正常通过的数据
resolve({
status: 'success',
data: i,
date: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
});
}, i)
}).catch(err => err);
asyncPools(2, [1000, 5000, 3000, 2000], timeout)
.then(res => {
console.log(res)
}).catch(err => {
throw Error(err)
}).finally(() => {
console.log('结束...')
});
asyncPools(2, [2000, 1000, 4000, 2000], timeout)
.then(res => {
console.log(res)
}).catch(err => {
throw Error(err)
}).finally(() => {
console.log('结束...')
});
输出
[
{ status: 'success', data: 2000, date: '2021-08-18 14:07:33' },
{ status: 'success', data: 1000, date: '2021-08-18 14:07:32' },
{ status: 'success', data: 4000, date: '2021-08-18 14:07:36' },
{ status: 'success', data: 2000, date: '2021-08-18 14:07:35' }
]
结束...
[
{ status: 'success', data: 1000, date: '2021-08-18 14:07:32' },
{ status: 'success', data: 5000, date: '2021-08-18 14:07:36' },
{ status: '请求超时!', data: 3000, date: '2021-08-18 14:07:35' },
{ status: 'success', data: 2000, date: '2021-08-18 14:07:37' }
]
结束...
function asyncPools(factory, maxRun /*并发最大数量*/ , intiArray = [] /*初始化任务列表*/ , startIndex = 0, executing = [] /*运行中*/ ) {
let results = []; // 结果集
function promiseMax() {
// 最后一个resolve状态,会进入外层返回Promise.then
if (startIndex >= intiArray.length) return Promise.resolve();
let mi = intiArray[startIndex++]
let pro = factory(mi); // 当前任务对象
if (pro instanceof Promise) {
pro.then(() => {
executing.splice(executing.indexOf(pro), 1);
}).catch(err => err)
executing.push(pro);
results.push(pro);
}
// 监听每完成一个就再放一个
if (executing.length >= maxRun) {
// race: 哪个 Promise 对象最快得到结果,就返回那个结果,不管结果本身是成功状态还是失败状态。
return Promise.race(executing).then(promiseMax);
} else {
// 改写一下保证then链式调用
return Promise.resolve().then(promiseMax);
}
}
// 注意:这不管是all还是allSettled,子任务失败时都会返回【主要是race函数的作用】
return promiseMax().then(() => Promise.all(results));
}
第一种写法
// 模拟请求操作
const timeout = i => new Promise((resolve, reject) => {
setTimeout(() => {
// 自定义错误提醒
if (i === 3000) {
// console.log(param, ' failed')
return reject({
status: 'error',
data: i,
date: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
})
}
console.log(i);
// 正常通过的数据
resolve({
status: 'success',
data: 200,
date: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
});
}, i)
}).catch(err => err); // 这里对应reject的status状态信息啦
// /*模拟函数: 这里模拟延迟操作*/
asyncPools(timeout, 5, [1000, 5000, 3000, 2000, 7000, 1000, 5000, 3000, 2000, 1000]).then(res => {
console.log(res)
}).catch(err => {
throw Error(err)
}).finally(() => {
console.log('结束...')
});
第二种写法
/*模拟函数: 这里模拟延迟操作*/
asyncPools((i) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 自定义错误提醒
if (i === 3000) {
// console.log(param, ' failed')
return reject({
status: 'error',
data: i,
date: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
})
}
console.log(i);
// 正常通过的数据
resolve({
status: 'success',
data: 200,
date: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
});
}, i)
}).catch(err => err); // 这里对应reject的status状态信息啦
}, 5, [1000, 5000, 3000, 2000, 7000, 1000, 5000, 3000, 2000, 1000]).then(res => {
console.log(res)
}).catch(err => {
throw Error(err)
}).finally(() => {
console.log('结束...')
});