直接上代码,后面再补充解释。
简化版,具有并发控制,顺序执行,返回一个promise等待所有任务完成后执行回调。
class PQueue {
constructor(concurrency = 1) {
this.concurrency = concurrency;
this.runningCount = 0;
this.queue = [];
this.onIdleResolve = null;
}
add(task) {
return new Promise((resolve, reject) => {
const taskWrapper = async () => {
try {
const result = await task();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.runningCount--;
this.dequeue();
}
};
this.queue.push(taskWrapper);
this.dequeue();
});
}
dequeue() {
if (this.runningCount >= this.concurrency) {
return;
}
if (this.queue.length === 0) {
if (this.runningCount === 0 && this.onIdleResolve) {
this.onIdleResolve();
}
return;
}
const task = this.queue.shift();
this.runningCount++;
task();
}
onIdle() {
return new Promise((resolve) => {
if (this.runningCount === 0 && this.queue.length === 0) {
resolve();
} else {
this.onIdleResolve = resolve;
}
});
}
}
使用,参考p-queue原理实现的,所以使用也相似
const PQueue = require('p-queue');
// 创建PQueue实例,并设置最大并发数
const queue = new PQueue({ concurrency: 2 });
// 添加任务到队列
queue.add(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('Task 1');
resolve();
}, 1000);
});
});
queue.add(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('Task 2');
resolve();
}, 500);
});
});
queue.add(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('Task 3');
resolve();
}, 800);
});
});
// 执行任务队列
queue.onIdle().then(() => {
console.log('All tasks completed');
});
加入了优先级版本。
class PQueue {
constructor(concurrency = 1) {
this.concurrency = concurrency;
this.runningCount = 0;
this.queue = [];
this.onIdleResolve = null;
}
add(task, priority = 0) {
return new Promise((resolve, reject) => {
const taskWrapper = async () => {
try {
const result = await task();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.runningCount--;
this.dequeue();
}
};
const taskItem = { task: taskWrapper, priority };
this.insertTaskWithPriority(taskItem);
this.dequeue();
});
}
insertTaskWithPriority(taskItem) {
let inserted = false;
for (let i = 0; i < this.queue.length; i++) {
if (taskItem.priority > this.queue[i].priority) {
this.queue.splice(i, 0, taskItem);
inserted = true;
break;
}
}
if (!inserted) {
this.queue.push(taskItem);
}
}
dequeue() {
if (this.runningCount >= this.concurrency) {
return;
}
if (this.queue.length === 0) {
if (this.runningCount === 0 && this.onIdleResolve) {
this.onIdleResolve();
}
return;
}
const taskItem = this.queue.shift();
this.runningCount++;
taskItem.task();
}
onIdle() {
return new Promise((resolve) => {
if (this.runningCount === 0 && this.queue.length === 0) {
resolve();
} else {
this.onIdleResolve = resolve;
}
});
}
}
使用
queue.add(() => {
// 任务逻辑...
}, 1); // 优先级为1
queue.add(() => {
// 任务逻辑...
}, 2); // 优先级为2