gpt4 book ai didi

javascript - 最大并发任务数为 "running"的异步任务管理器

转载 作者:行者123 更新时间:2023-12-05 05:12:07 24 4
gpt4 key购买 nike

我正在尝试实现两个可以在 JavaScript 中处理异步任务的类:

  • Task:模拟使用 setTimeout 执行任务。计时器到期后,任务即被视为已完成。
  • TaskManager:有一个 capacity 参数来限制可以并行执行的任务的数量。

我想如果我可以递归调用 loop 函数,只是为了继续检查一项工作是否完成,我就可以继续下一项工作。但这会立即导致“超出最大调用堆栈大小”错误。

谁能解释一下我该如何解决这个问题?

class Task {
constructor(time) {
this.time = time;
this.running = 0;
}
run(limit, jobs, index) {
setTimeout(() => {
console.log('hello', index);
this.done(limit, jobs, index);
}, this.time);
}
done(limit, jobs, index) {
jobs.splice(index, 1);
console.log(jobs);
}
}

class TaskManager {
constructor(capacity) {
this.capacity = capacity;
this.jobs = [];
this.index = 0;
this.running = 0;
this.pending = [];
}
push(tk) {
this.jobs.push(tk);
this.index += 1;
const loop = () => {
if (this.jobs.length === 0) {
return;
}
if (this.jobs.length <= this.capacity) {
this.running += 1;

tk.run(this.capacity, this.jobs, this.index-1);
return;
}
loop();
}
loop();
}
}

const task = new Task(100);
const task1 = new Task(200);
const task2 = new Task(400);
const task3 = new Task(5000);
const task4 = new Task(6000);
const manager = new TaskManager(3);
manager.push(task);
manager.push(task1);
manager.push(task2);
manager.push(task3);
manager.push(task4);

最佳答案

你不应该实现忙循环,因为这会阻塞事件循环,因此不会处理用户 UI 事件或 setTimeout 事件。

改为响应异步事件。

如果您让 setTimeout 回调解决一个 Promise,这并不难做到。

我彻底修改了你的脚本。这是结果:

class Task {
constructor(id, time) {
this.id = id;
this.time = time;
}
run() {
console.log(this + ' launched.');
return new Promise(resolve => {
setTimeout(() => {
console.log(this + ' completed.');
resolve();
}, this.time);
});
}
toString() {
return `Task ${this.id}[${this.time}ms]`;
}
}

class TaskManager {
constructor(capacity) {
this.capacity = capacity;
this.waiting = [];
this.running = [];
}
push(tk) {
this.waiting.push(tk);
if (this.running.length < this.capacity) {
this.next();
} else {
console.log(tk + ' put on hold.');
}
}
next() {
const task = this.waiting.shift();
if (!task) {
if (!this.running.length) {
console.log("All done.");
}
return; // No new tasks
}
this.running.push(task);
const runningTask = task.run();
console.log("Currently running: " + this.running);
runningTask.then(() => {
this.running = this.running.filter(t => t !== task);
console.log("Currently running: " + this.running);
this.next();
});
}
}

const a = new Task('A', 100);
const b = new Task('B', 200);
const c = new Task('C', 400);
const d = new Task('D', 5000);
const e = new Task('E', 6000);
const manager = new TaskManager(3);
manager.push(a);
manager.push(b);
manager.push(c);
manager.push(d);
manager.push(e);

关于javascript - 最大并发任务数为 "running"的异步任务管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54901078/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com