ascor
Version:
一些常用的简单的js工具
98 lines (97 loc) • 3.22 kB
JavaScript
import { EventEmitter } from "./EventEmitter";
export class Queue extends EventEmitter {
constructor(config = { autoStart: false, workers: [], concurrency: Infinity }) {
var _a, _b, _c;
super();
this.workers = []; // 任务列表
this.workersCache = []; // 保存原来的任务列表
this.pending = 0; // 进行中的任务数量
this.autoStart = false; // 是否自动开始
this.isRuning = false; //是否执行中
this.isAborted = false; //是否中止了
this.concurrency = Infinity; //并发数量
this.autoStart = (_a = config === null || config === void 0 ? void 0 : config.autoStart) !== null && _a !== void 0 ? _a : false; // 是否自动开始
this.concurrency = (_b = config === null || config === void 0 ? void 0 : config.concurrency) !== null && _b !== void 0 ? _b : Infinity; //并发数量
this.push(...((_c = config === null || config === void 0 ? void 0 : config.workers) !== null && _c !== void 0 ? _c : []));
}
/**
* 获取执行中和队列中的数量,已执行完的不计算在内
*/
get length() {
return this.workers.length + this.pending;
}
/**
* 添加队列任务
* @param {...any} workers 任务列表
*/
push(...workers) {
this.workers.push(...workers);
this.workersCache.push(...workers);
if (this.autoStart) {
this.start();
}
}
/**
* 执行下一任务
* @param {*} worker
* @returns
*/
next(worker = null) {
if (this.isAborted) {
return false;
}
if (!worker) {
if (this.length <= 0) {
this.isRuning = false;
this.emit("end", null);
return false;
}
if (this.workers.length <= 0) {
return false;
}
}
this.pending++;
let _worker = worker !== null && worker !== void 0 ? worker : this.workers.shift();
Promise.resolve(typeof _worker == "function" ? _worker() : _worker)
.then((res) => {
!this.isAborted && this.emit("success", res);
})
.catch((error) => {
!this.isAborted && this.emit("error", error, _worker);
})
.finally(() => {
this.pending--;
!this.isAborted && this.next();
});
}
/**
* 开始任务
*/
start() {
if (this.isAborted) {
// 如果之前已经中止过,则重新取之前的全部队列,重新执行
this.workers = [...this.workersCache];
}
this.isAborted = false;
if (!this.isRuning) {
this.emit("start");
this.isRuning = true;
}
while (this.concurrency > this.pending && this.workers.length > 0 && !this.isAborted) {
this.next();
}
}
/**
* 中止任务
*/
abort() {
this.isAborted = true;
if (this.isRuning) {
this.isRuning = false;
this.emit("end", new Error("The queue is aborted !"));
}
}
end() {
this.abort();
}
}