diff --git a/src/utils/poll.ts b/src/utils/poll.ts index 6c82ad52ed..88851097e9 100644 --- a/src/utils/poll.ts +++ b/src/utils/poll.ts @@ -1,93 +1,90 @@ const DEFAULT_INTERVAL = 15000; const DEFAULT_GRACE_RATIO = 0.33; -export class Poll { - private _cancelled = true; - - // This flag is true when the poll is not running. You may - // use it in your code to determine if you should proceed. - public get cancelled(): boolean { - return this._cancelled; - } - - private _counter = 0; - public get counter(): number { - return this._counter; - } - - private graceInterval: number; - private pollInterval: NodeJS.Timer | null = null; - private lastCompleteTime = 0; - private blocked = false; - private isTabActive: boolean; +export interface Poll { + poll: (opts?: { forced?: boolean }) => void; + start: () => void; + stop: () => void; + destroy: () => void; +} - constructor( - private fn: (poll: Poll) => Promise, - private interval: number, - graceRatio: number, - isTabActive: boolean, - ) { - this.poll = this.poll.bind(this); - this.graceInterval = this.interval * graceRatio; - this.isTabActive = isTabActive; - } +const pollFn = ( + fn: () => Promise, + interval: number, + graceRatio: number, + isTabActive: boolean, +) => { + let cancelled = true; + const graceInterval: number = interval * graceRatio; + let pollInterval: NodeJS.Timer | null = null; + let lastCompleteTime = 0; + let counter = 0; + let blocked = false; - public async poll(opts?: { forced?: boolean }) { + const poll = async (opts?: { forced?: boolean }) => { + console.log('POLL', counter); // Only run poll if the previous call has finished and the poll // is not cancelled - if (this.cancelled || this.blocked) { + if (cancelled || blocked) { return; } const forced = opts && opts.forced; // Return if we're invisible, unless it's first run - if (!forced && !this.isTabActive && this.lastCompleteTime !== 0) { + if (!forced && !isTabActive && lastCompleteTime !== 0) { return; } - if (!forced && Date.now() - this.lastCompleteTime < this.graceInterval) { + if (!forced && Date.now() - lastCompleteTime < graceInterval) { return; } - this.blocked = true; + blocked = true; try { - await this.fn(this); - this.lastCompleteTime = Date.now(); + await fn(); + lastCompleteTime = Date.now(); } finally { - this._counter++; - this.blocked = false; + counter++; + blocked = false; } - } + }; - public start() { + const start = () => { // Only start polling if it is currently stopped. - if (this.pollInterval != null) { + if (pollInterval != null) { return; } - this.lastCompleteTime = 0; - this._cancelled = false; - this.pollInterval = setInterval(this.poll, this.interval); + lastCompleteTime = 0; + cancelled = false; + pollInterval = setInterval(poll, interval); // Also run a poll instantly, as we wanted to start it *now*, // not X time in the future. - return this.poll(); - } + return poll(); + }; - public stop() { - if (this.pollInterval) { - clearInterval(this.pollInterval); + const stop = () => { + if (pollInterval) { + clearInterval(pollInterval); } - this._cancelled = true; - this.pollInterval = null; - } + cancelled = true; + pollInterval = null; + }; - public destroy() { - this.stop(); - this.fn = async () => undefined; // break possible cyclic reference - } -} + const destroy = () => { + stop(); + fn = async () => undefined; // break possible cyclic reference + }; + + return { + poll, + start, + stop, + destroy, + }; +}; export const createPoll = ( - fn: (poll: Poll) => Promise, + fn: () => Promise, interval: number = DEFAULT_INTERVAL, isTabActive: boolean = true, graceRatio: number = DEFAULT_GRACE_RATIO, -) => new Poll(fn, interval, graceRatio, isTabActive); +) => pollFn(fn, interval, graceRatio, isTabActive);