If more requests are made within the specified interval than the specified number, it waits until the oldest one is older than the interval before making the next request in the queue.
Questo script non dovrebbe essere installato direttamente. È una libreria per altri script da includere con la chiave // @require https://update.greasyfork.org/scripts/559799/1719672/Real-Time-Rate-Limiting-Queue.js
This library uses Mike Diarmid's Denque https://github.com/Salakar — copyright (c) 2018 Invertase Limited https://github.com/invertase/denque
Sometimes, a script may need to make many requests to a site. If the script makes enough requests in a short enough time, the site may consequently become annoyed at their server getting hammered. Some sites actually require scripts to limit requests to a published frequency or face consequences of some sort. This class allows you to automatically limit the frequency of requests that your script makes.
What makes this class special is that the rate is limited in real time, which all but guarantees that any given request will be made the moment the timeline of your past requests permits it, without, for example, waiting for a multiple of the interval to pass, or recomputing an equivalent rate based on a different interval.
This class requires some familiarity with the use of javascript Promises. A good primer is https://javascript.info/async.
To use, access
globalThis[meta]
where meta is a string key composed of the @required script's metadata @namespace, @name, and the major version number of @version, joined with colons. I.e.,
globalThis["github.com/JasonAMelancon:Real-Time-Rate-Limiting-Queue:1"]
In a script that @requires this script, the above expression will evaluate to the Real-time Rate-limiting Queue class, which can be assigned to a variable, which is then usable as the class identifier.
(Only the major version is used because updating the script changes the version number, which would break this mechanism, but a new major version would typically break including scripts anyway.)
All documentation is available as JSDoc comments. Where this excerpt of the JSDoc differs from that found in the code, prefer the latter.
constructor(reqPerInterval, interval, concurrent, array, dequeOptions)Instantiates the queue.
reqPerIntervalRequests per interval. The numerator of the queue rate parameter. Will be set to the default of 1 if not a valid positive number.
intervalThe denominator of the queue rate parameter in milliseconds. Will be set to the default of 0 if not a valid non-negative number. 0 disables rate limit.
concurrentPass in false if each item should wait for the last to finish before executing. Only inherently asynchronous operations may be concurrent.
arrayCan be supplied if the desired item queue exists as an array already. Note that queue execution only begins on enqueueing an object.
dequeOptionsPassed on to internal deque class, which currently ignores it. See Denque module (https://github.com/invertase/denque).
enqueue(item)Enqueue the item object itself (not a copy).
itemTo be useful, this must have a function in its "executor" or "callback" property. This is the request whose rate of calling will be controlled. If supplied, theexecutorproperty must contain a function of the kind thatPromise()takes. If there is acallbackand noexecutor, the callback should return either a truthy value (which may be a result), or a falsy value indicating failure. In either case, the item will be given a "timestamp" property containing the javascript datetime of the request execution, a boolean "success" property, and a "promise" property containing aPromise, automatically constructed from theexecutorif supplied, holding the result of the request. RejectedPromises and failedcallbacks will not count toward the rate limit. These should result from, for example, fetching an invalid URL or having no network, but not from a404 Not Found, which would typically still count since it requires server time.Returns a
Promisethat resolves to the supplied item once itspromiseproperty is settled. Do not confuse these twoPromises! This one resolves to the enqueued item when its request is settled, while thePromiseon the item itself contains the result of the request. This is in order to make the other information on the item available when the request result is accessed.
Here is a brief example of how an instance of the queue class, named
myRtrlQueue, would be created and used in practice.const Rtrlq = globalThis["github.com/JasonAMelancon:Real-Time-Rate-Limiting-Queue:1"]; const myRtrlQueue = new Rtrlq(3, Rtrlq.seconds(5)); // max of 3 requests every 5 seconds const URL = "https://www.site.net/api/some/text/"; // ... const queueItem = myRtrlQueue.enqueue({ executor: (resolve, reject) => fetch(URL).then(resolve, reject), id: 69105 }); // ... // now examine request result, along with any associated data you put on the queue item queueItem.then(item => item.promise .then(response => { if (!response.ok) { throw new Error(`${response.status} - ${response.statusText}`); } console.log(`Queued request ${item.id} succeeded: ${response.body}`); }) .catch(err => console.error(`Queued request ${item.id} failed: ${err}`)));