异步任务管理器

时间:2019-02-27 08:31:48

标签: javascript asynchronous async-await

嗨,我正在尝试实现两个处理JavaScript中异步任务的类: 一类称为Task,它使用setTimeout运行任务 另一个称为TaskManager的类负责限制可一次执行的任务数量。 我以为我可以递归地调用循环函数只是为了继续检查一项工作是否完成,因此我可以继续进行下一项工作。有人可以给我任何指导以解决此问题吗? (此外,如果有人可以提供一些类似的JS异步练习/网站进行练习,我将不胜感激)

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

1 个答案:

答案 0 :(得分:0)

您不应该实现繁忙循环,因为它会阻塞事件循环,因此不会处理用户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);