1. 基本版
要注意的就是通过利用runCnt和maxCnt控制执行逻辑。
class Scheduler {
queue = [];
runCnt = 0;
constructor(maxCnt) {
this.maxCnt = maxCnt;
}
add(time, data) {
this.queue.push(() => promiseCreator(time, data));
this.request();
}
request() {
if (this.queue.length && this.runCnt < this.maxCnt) {
this.runCnt++;
this.queue
.shift()()
.then((data) => {
this.runCnt--;
console.log(data);
this.request();
});
}
}
}
const promiseCreator = (time, data) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data);
}, time);
});
};
const scheduler = new Scheduler(2);
scheduler.add(1000, 1);
scheduler.add(500, 2);
scheduler.add(300, 3);
scheduler.add(400, 4);
// 2 3 1 4
函数实现,要求输出一个二维数组:
4个promse,分别是1s,3s,4s,0.5s。第1个执行完了的.then执行第3个,第2个执行完了的.then执行第4个。所以输出二维数组[ [ 1000, 3000 ], [ 4000, 500 ] ]
const timeout = (time, value) =>
new Promise((resolve) => {
setTimeout(() => resolve(value), time);
});
doLimit(
[
() => timeout(1000, 1000),
() => timeout(2500, 2500),
() => timeout(2000, 2000),
() => timeout(500, 500)
],
2
).then((value) => {
console.log(value);
});
async function doLimit(proimseFnArr, limit) {
const resArr = [];
// 用于存储当前正在执行的 Promise 的数组
const activePromiseArr = [];
// 用于记录最新完成的 Promise 的索引
let latestFulfilledIndex;
for (let i = 0; i < proimseFnArr.length; i++) {
const promise = proimseFnArr[i]();
if (i < limit) {
activePromiseArr[i] = promise;
promise.then((value) => {
// 更新最新完成的 Promise 的索引
latestFulfilledIndex = i;
// 创建数组 将结果存储在对应索引的位置
resArr[i] = [value];
});
} else {
const currentIndex = latestFulfilledIndex; // 获取最新完成的 Promise 的索引
activePromiseArr[currentIndex] = promise; // 将当前的 Promise 存储在 activePromiseArr 中
promise.then((value) => {
latestFulfilledIndex = currentIndex; // 更新最新完成的 Promise 的索引
resArr[currentIndex].push(value); // 将结果追加到对应索引的位置
});
}
if (activePromiseArr.length === limit) {
await Promise.race(activePromiseArr);
}
}
await Promise.all(activePromiseArr);
return resArr;
}