UNPKG

power-tasks

Version:

Powerful task management for JavaScript

92 lines (91 loc) 2.74 kB
import DoublyLinked from "doublylinked"; import { AsyncEventEmitter } from "strict-typed-events"; import { Task } from "./task.js"; export class TaskQueue extends AsyncEventEmitter { constructor(options) { super(); this._queue = new DoublyLinked(); this._running = new Set(); this.maxQueue = options?.maxQueue; this.concurrency = options?.concurrency; this._paused = !!options?.paused; } get size() { return this._queue.length + this._running.size; } get running() { return this._running.size; } get queued() { return this._queue.length; } get paused() { return this._paused; } pause() { this._paused = true; } resume() { this._paused = false; setImmediate(() => this._pulse()); } clearQueue() { this._queue.forEach((task) => task.abort()); this._queue = new DoublyLinked(); } abortAll() { if (!this.size) return; this.clearQueue(); this._running.forEach((task) => task.abort()); } async wait() { if (!this.size) return Promise.resolve(); return new Promise((resolve) => { this.once("finish", resolve); }); } enqueuePrepend(task) { return this._enqueue(task, true); } enqueue(task) { return this._enqueue(task, false); } _enqueue(task, prepend) { if (this.maxQueue && this.size >= this.maxQueue) throw new Error(`Queue limit (${this.maxQueue}) exceeded`); const taskInstance = task instanceof Task ? task : new Task(task); Object.defineProperty(taskInstance, "_isManaged", { configurable: false, writable: false, enumerable: false, value: true, }); taskInstance.once("error", (...args) => this.emitAsync("error", ...args)); this.emit("enqueue", taskInstance); if (prepend) this._queue.unshift(taskInstance); else this._queue.push(taskInstance); this._pulse(); return taskInstance; } _pulse() { if (this.paused) return; while (!this.concurrency || this._running.size < this.concurrency) { const task = this._queue.shift(); if (!task) return; this._running.add(task); task.prependOnceListener("finish", () => { this._running.delete(task); if (!(this._running.size || this._queue.length)) return this.emit("finish"); this._pulse(); }); task.start(); } } }