javascript-实现有并发数限制的任务调度器

loading 2023年03月10日 124次浏览

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;
}