Диспетчер асинхронных задач - PullRequest
0 голосов
/ 27 февраля 2019

Здравствуйте, я пытаюсь реализовать два класса, которые имеют дело с асинхронными задачами в 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 голосов
/ 27 февраля 2019

Не следует реализовывать цикл занятости, поскольку он будет блокировать цикл событий, и поэтому никакие события пользовательского интерфейса или события setTimeout не будут обрабатываться.

Вместо этого реагируйте на асинхронные события.

Если вы позволите обратному вызову setTimeout разрешить Обещание, это не так сложно сделать.

Я довольно сильно изменил ваш скрипт.Вот результат:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...