Очередь хранит ожидающие задачи и число активных обработчиков; новый запуск разрешён только пока active меньше лимита.
class Queue {
Очередь хранит ожидающие задачи и число активных обработчиков; новый запуск разрешён только пока active меньше лимита.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
class Queue { }
const processTask = (task, resolve) => { // время обработки задачи от 500 до 1000 const workTime = 500 + Math.floor(Math.random() * 500)
setTimeout(() => { console.log(task) resolve() }, workTime) } const paralleledTasks = 2 const whenEmpty = () => console.log('Queue is empty')
const queue = new Queue(processTask, paralleledTasks, whenEmpty)
queue.add('task 1') queue.add('task 2') queue.add('task 3') queue.loop()
/* example output: task 1 task 2 task 3 Queue is empty
- несколько задач обрабатывается
- задано количество одновременно, по горе
- paralleledTasks = 1 значит может быть
- не последовательно как тут сначала
- успели выполниться task 2, а потом task 1 */
Ответ
Очередь хранит ожидающие задачи и число активных обработчиков; новый запуск разрешён только пока active меньше лимита.
Для данного callback-контракта успешного завершения:
class Queue {
constructor(process, limit, whenEmpty) {
if (!Number.isInteger(limit) || limit < 1) throw new RangeError('limit');
this.process = process; this.limit = limit; this.whenEmpty = whenEmpty;
this.tasks = []; this.active = 0; this.started = false; this.notified = false;
}
add(task) {
this.tasks.push(task); this.notified = false;
if (this.started) this.loop();
}
loop() {
this.started = true;
while (this.active < this.limit && this.tasks.length) {
const task = this.tasks.shift();
this.active++;
let done = false;
this.process(task, () => {
if (done) return;
done = true; this.active--;
queueMicrotask(() => this.loop());
});
}
if (!this.tasks.length && !this.active && !this.notified) {
this.notified = true; this.whenEmpty();
}
}
}
Порядок завершения не гарантирован. Для production отдельно задают обработку ошибок, таймаут задачи и эффективное хранение большой очереди вместо shift.