【问题标题】:Async task manager异步任务管理器
【发布时间】:2019-02-27 08:31:47
【问题描述】:

您好,我正在尝试在 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);

【问题讨论】:

  • 您可以使用生成器来达到预期的效果。
  • Javascript 是严格的单线程的。没有任务将并行运行,而是它们同时运行(给人一种并行的错觉)。因此,任何无限循环,例如递归 loop() 函数将导致 setTimeout 永远不会运行,因此不会执行任何任务。解决办法是loop()本身必须是setTimeouted
  • 您可以阅读我对其他问题的回答以了解 javascript 中的异步“引擎”如何工作:stackoverflow.com/questions/29883525/…

标签: javascript asynchronous async-await


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-08
    • 2015-03-10
    • 2016-06-10
    • 1970-01-01
    相关资源
    最近更新 更多