可并发控制的 Promise.all
纯自己整的,不确定这样的实现是否正确,也不确定测试是否有说服力。
还是期待讨论和指教。
实现代码
Promise.myAllConcurrent = function (promiseArr, limit = 1) {
return new Promise((resolve, reject) => {
if (!promiseArr[Symbol.iterator]) {
throw new TypeError(`${promiseArr} is not iterable`);
}
if (!Array.isArray(promiseArr)) {
promiseArr = Array.from(promiseArr);
}
const resArr = [];
const len = promiseArr.length;
let count = 0;
let lastIndex = limit - 1;
// 不能用 count 来替代 lastIndex
// eg. 允许并发数为 3, 但总共有 10 个
// 任务 ① 处理完后, 开始处理任务 ④
// 假设任务 ④ 耗时较长,
// 任务 ④ 结束之前, 任务 ② 也处理好了
// 如果按照 count 去处理, 则此时任务 ③ 的回调会去处理任务 ②, 而非 任务 ⑤
// 如果按照 lastIndex 去处理, 则此时任务 ③ 的回调会去处理任务 ⑤
function takeOnePromise(resArr, index) {
Promise.resolve(promiseArr[index]).then(
value => {
resArr[index] = value;
count++;
lastIndex++;
if (count !== len) takeOnePromise(resArr, lastIndex);
else resolve(resArr);
},
reason => {
reject(reason);
}
);
}
const top = Math.min(limit, length);
for (let i = 0; i < top; i++) {
takeOnePromise(resArr, i);
}
});
}
测试代码
Promise.myAllConcurrent = function (promiseArr, limit = 1) {
return new Promise((resolve, reject) => {
if (!promiseArr[Symbol.iterator]) {
throw new TypeError(`${promiseArr} is not iterable`);
}
if (!Array.isArray(promiseArr)) {
promiseArr = Array.from(promiseArr);
}
const resArr = [];
const len = promiseArr.length;
let count = 0;
let lastIndex = limit - 1;
function takeOnePromise_timer(resArr, index) { // 为了测试, 包了一层计时器
setTimeout(() => {
Promise.resolve(promiseArr[index]).then(
value => {
resArr[index] = value;
count++;
lastIndex++;
if (count !== len) takeOnePromise_timer(resArr, lastIndex);
else resolve(resArr);
},
reason => {
reject(reason);
}
);
}, 2000);
}
for (let i = 0; i < limit; i++) {
// takeOnePromise(resArr, i);
takeOnePromise_timer(resArr, i);
}
// 计时器 定时查询 res的数量, 以此代替观测并发数
setInterval(() => {
console.log(resArr.length);
}, 1000);
});
}
const instance1 = new Promise(resolve => {
resolve('Promise —— 1');
});
const instance2 = new Promise(resolve => {
resolve('Promise —— 2');
});
const instance3 = new Promise(resolve => {
resolve('Promise —— 3');
});
const instance4 = new Promise(resolve => {
resolve('Promise —— 4');
});
const instance5 = new Promise(resolve => {
resolve('Promise —— 5');
});
const promiseArr = [instance1, instance2, instance3, instance4, instance5];
Promise.myAllConcurrent(promiseArr, 2).then((value) => {
console.log('finish —— promise');
console.log('value: ', value);
});