I am trying to implement two classes that can deal with asynchronous tasks in JavaScript:
- Class
Task: mimics the execution of a task withsetTimeout. Once the timer expires, the task is considered completed. - Class
TaskManager: has acapacityparameter to limit the numbers of tasks that can be executing in parallel.
I thought if I could just call the loop function recursively, just to keep checking if one job is done, I could proceed to the next job. But this leads immediately to a "Maximum call stack size exceeded" error.
Can someone explain how I can fix this?
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);
loop()function will causesetTimeoutto never run thus no tasks will ever execute. The solution is thatloop()itself must besetTimeouted