UNPKG

5.31 kBJavaScriptView Raw
1const x = Infinity;
2
3/**
4 * Waiter based on API rate limits you enter manually
5 *
6 * (Please read README in package to get further info)
7 *
8 * @param {Object} options
9 * @param {function} options.startWaitingCallback
10 * @param {function} options.endWaitingCallback
11 * @param {function} options.waitingTickCallback
12 * @param {Number} options.msBetweenTwoCalls
13 * @param {Number} options.minutelyLimit
14 * @param {Number} options.hourlyLimit
15 * @param {boolean} options.test
16 * @constructor
17 */
18function LimitWaiter(options) {
19 this.msWait = options ? options.msBetweenTwoCalls ? Number.isSafeInteger(options.msBetweenTwoCalls) ? options.msBetweenTwoCalls > 0 ? options.msBetweenTwoCalls : 0 : 0 : 0 : 0;
20 this.mLim = options ? options.minutelyLimit ? Number.isSafeInteger(options.minutelyLimit) ? options.minutelyLimit > 0 ? options.minutelyLimit : x : x : x : x;
21 this.hLim = options ? options.hourlyLimit ? Number.isSafeInteger(options.hourlyLimit) ? options.hourlyLimit > 0 ? options.hourlyLimit : x : x : x : x;
22 this.startWaitingCallback = options ? options.startWaitingCallback ? options.startWaitingCallback : function () { } : function () { };
23 this.endWaitingCallback = options ? options.endWaitingCallback ? options.endWaitingCallback : function () { } : function () { };
24 this.waitingTickCallback = options ? options.waitingTickCallback ? options.waitingTickCallback : function () { } : function () { };
25 this.test = options ? options.test ? options.test : false : false;
26 this.mC = 0;
27 this.hC = 0;
28 this.totalC = 0;
29 this.callbackQueue = [];
30 this.alreadyWorking = false;
31}
32
33LimitWaiter.prototype.wait = function (apiCallFunction) {
34 this.callbackQueue.push(apiCallFunction);
35 if (!this.alreadyWorking) {
36 workOnQueueLW(this); // trigger working
37 }
38}
39
40let workOnQueueLW = async (ctx) => {
41 while (ctx.callbackQueue.length > 0) {
42 ctx.alreadyWorking = true;
43 await checkWaitingLW(ctx)
44 .then(() => {
45 let cb = ctx.callbackQueue[0];
46 ctx.callbackQueue.shift();
47 cb();
48 // manage counters
49 ctx.mC++;
50 ctx.hC++;
51 ctx.totalC++;
52 })
53 }
54 ctx.alreadyWorking = false;
55}
56
57function checkWaitingLW(ctx) {
58 return new Promise(function (resolve) {
59 if (ctx.mC < ctx.mLim && ctx.hC < ctx.hLim) {
60 if (ctx.msWait > 0) {
61 ctx.startWaitingCallback({
62 millisecondsToWait: ctx.msWait
63 })
64 waitMilliseconds(ctx.msWait)
65 .then(() => {
66 ctx.endWaitingCallback({
67 millisecondsWaited: ctx.msWait
68 })
69 resolve();
70 })
71 } else {
72 resolve(); // do not have to wait
73 }
74 } else if (ctx.hC >= ctx.hLim) {
75 let d = new Date().getMinutes();
76 let minutes = 60 - d;
77 let seconds = minutes * 60;
78 ctx.startWaitingCallback({
79 currentCallsInAnHour: ctx.hC,
80 hourlyLimit: ctx.hLim,
81 secondsToWaitTilNextHour: seconds
82 })
83 seconds = ctx.test ? 5 : seconds;
84 waitSeconds(seconds, ctx.waitingTickCallback)
85 .then(() => {
86 ctx.hC = ctx.mC = 0;
87 ctx.endWaitingCallback({
88 secondsWaited: seconds,
89 callsInQueue: ctx.callbackQueue.length,
90 totalCalls: ctx.totalC
91 })
92 resolve()
93 })
94 } else if (ctx.mC >= ctx.mLim) {
95 let d = new Date().getSeconds();
96 let seconds = 60 - d;
97 ctx.startWaitingCallback({
98 currentCallsInAMinute: ctx.mC,
99 minutelyLimit: ctx.mLim,
100 secondsToWaitTilNextMinute: seconds
101 })
102 seconds = ctx.test ? 5 : seconds;
103 waitSeconds(seconds, ctx.waitingTickCallback)
104 .then(() => {
105 ctx.mC = 0;
106 ctx.endWaitingCallback({
107 secondsWaited: seconds,
108 callsInQueue: ctx.callbackQueue.length,
109 totalCalls: ctx.totalC
110 })
111 resolve()
112 })
113 }
114 })
115}
116
117function waitMilliseconds(milliseconds) {
118 return new Promise(function (resolve) {
119 let t = setTimeout(function () {
120 clearTimeout(t);
121 resolve();
122 }, milliseconds)
123 })
124}
125
126function waitSeconds(seconds, tickCallback) {
127 return new Promise(function (resolve) {
128 let count = 1;
129 let v = setInterval(function () {
130 tickCallback({
131 secondsToWait: seconds - count,
132 secondsWaited: count
133 })
134 count++;
135 if (count > seconds) {
136 clearInterval(v);
137 resolve();
138 }
139 }, 1000)
140 })
141}
142
143exports.LimitWaiter = LimitWaiter;
\No newline at end of file