您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Asynchronous function queue with adjustable concurrency.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/482311/1297427/queue.js
- // ==UserScript==
- // @name queue
- // @description Asynchronous function queue with adjustable concurrency.
- // @author Jesse Tane
- // @namespace https://github.com/jessetane/queue
- // @version 7.0.0
- // @license MIT
- // ==/UserScript==
- var { Queue, QueueEvent } = (function (exports) {
- 'use strict';
- const has = Object.prototype.hasOwnProperty;
- /**
- * Since CustomEvent is only supported in nodejs since version 19,
- * you have to create your own class instead of using CustomEvent
- * @see https://github.com/nodejs/node/issues/40678
- * */
- class QueueEvent extends Event {
- constructor (name, detail) {
- super(name);
- this.detail = detail;
- }
- }
- class Queue extends EventTarget {
- constructor (options = {}) {
- super();
- const { concurrency = Infinity, timeout = 0, autostart = false, results = null } = options;
- this.concurrency = concurrency;
- this.timeout = timeout;
- this.autostart = autostart;
- this.results = results;
- this.pending = 0;
- this.session = 0;
- this.running = false;
- this.jobs = [];
- this.timers = [];
- this.addEventListener('error', this._errorHandler);
- }
- _errorHandler (evt) {
- this.end(evt.detail.error);
- }
- pop () {
- return this.jobs.pop()
- }
- shift () {
- return this.jobs.shift()
- }
- indexOf (searchElement, fromIndex) {
- return this.jobs.indexOf(searchElement, fromIndex)
- }
- lastIndexOf (searchElement, fromIndex) {
- if (fromIndex !== undefined) return this.jobs.lastIndexOf(searchElement, fromIndex)
- return this.jobs.lastIndexOf(searchElement)
- }
- slice (start, end) {
- this.jobs = this.jobs.slice(start, end);
- return this
- }
- reverse () {
- this.jobs.reverse();
- return this
- }
- push (...workers) {
- const methodResult = this.jobs.push(...workers);
- if (this.autostart) this._start();
- return methodResult
- }
- unshift (...workers) {
- const methodResult = this.jobs.unshift(...workers);
- if (this.autostart) this._start();
- return methodResult
- }
- splice (start, deleteCount, ...workers) {
- this.jobs.splice(start, deleteCount, ...workers);
- if (this.autostart) this._start();
- return this
- }
- get length () {
- return this.pending + this.jobs.length
- }
- start (callback) {
- if (this.running) throw new Error('already started')
- let awaiter;
- if (callback) {
- this._addCallbackToEndEvent(callback);
- } else {
- awaiter = this._createPromiseToEndEvent();
- }
- this._start();
- return awaiter
- }
- _start () {
- this.running = true;
- if (this.pending >= this.concurrency) {
- return
- }
- if (this.jobs.length === 0) {
- if (this.pending === 0) {
- this.done();
- }
- return
- }
- const job = this.jobs.shift();
- const session = this.session;
- const timeout = (job !== undefined) && has.call(job, 'timeout') ? job.timeout : this.timeout;
- let once = true;
- let timeoutId = null;
- let didTimeout = false;
- let resultIndex = null;
- const next = (error, ...result) => {
- if (once && this.session === session) {
- once = false;
- this.pending--;
- if (timeoutId !== null) {
- this.timers = this.timers.filter(tID => tID !== timeoutId);
- clearTimeout(timeoutId);
- }
- if (error) {
- this.dispatchEvent(new QueueEvent('error', { error, job }));
- } else if (!didTimeout) {
- if (resultIndex !== null && this.results !== null) {
- this.results[resultIndex] = [...result];
- }
- this.dispatchEvent(new QueueEvent('success', { result: [...result], job }));
- }
- if (this.session === session) {
- if (this.pending === 0 && this.jobs.length === 0) {
- this.done();
- } else if (this.running) {
- this._start();
- }
- }
- }
- };
- if (timeout) {
- timeoutId = setTimeout(() => {
- didTimeout = true;
- this.dispatchEvent(new QueueEvent('timeout', { next, job }));
- next();
- }, timeout);
- this.timers.push(timeoutId);
- }
- if (this.results != null) {
- resultIndex = this.results.length;
- this.results[resultIndex] = null;
- }
- this.pending++;
- this.dispatchEvent(new QueueEvent('start', { job }));
- job.promise = job(next);
- if (job.promise !== undefined && typeof job.promise.then === 'function') {
- job.promise.then(function (result) {
- return next(undefined, result)
- }).catch(function (err) {
- return next(err || true)
- });
- }
- if (this.running && this.jobs.length > 0) {
- this._start();
- }
- }
- stop () {
- this.running = false;
- }
- end (error) {
- this.clearTimers();
- this.jobs.length = 0;
- this.pending = 0;
- this.done(error);
- }
- clearTimers () {
- this.timers.forEach(timer => {
- clearTimeout(timer);
- });
- this.timers = [];
- }
- _addCallbackToEndEvent (cb) {
- const onend = evt => {
- this.removeEventListener('end', onend);
- cb(evt.detail.error, this.results);
- };
- this.addEventListener('end', onend);
- }
- _createPromiseToEndEvent () {
- return new Promise((resolve, reject) => {
- this._addCallbackToEndEvent((error, results) => {
- if (error) reject(error);
- else resolve(results);
- });
- })
- }
- done (error) {
- this.session++;
- this.running = false;
- this.dispatchEvent(new QueueEvent('end', { error }));
- }
- }
- exports.Queue = Queue;
- exports.QueueEvent = QueueEvent;
- return exports;
- })({});
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址