Skip to content

Instantly share code, notes, and snippets.

@NoTimeForHero
Created March 31, 2023 01:30
Show Gist options
  • Save NoTimeForHero/d4682b82fadc7ad89d6d02bb439886d9 to your computer and use it in GitHub Desktop.
Save NoTimeForHero/d4682b82fadc7ad89d6d02bb439886d9 to your computer and use it in GitHub Desktop.
type PollingConfig = {
timeout?: number;
interval?: number;
initialTimeout?: number
};
type RequestFnResult <T> = { pending: true } | { data : T };
type Callback <T> = () => Promise<RequestFnResult<T>>;
export const TimeoutError = Symbol('TimeoutError!');
// Slow alternative:
// export class TimeoutError extends Error {}
export const polling = <T>(callback: Callback<T>, config?: PollingConfig) : Promise<T> =>
new Promise<T>((resolve, reject) => {
const {
timeout = 60000,
interval = 1000,
initialTimeout = 500
} = config ?? {};
let timerValue = initialTimeout;
const onTick = async () => {
try {
const start = window.performance.now();
const result = await callback();
const finish = window.performance.now();
timerValue += finish - start;
const timeIsOver = timerValue >= timeout;
if (timeIsOver) reject(TimeoutError);
else if ('pending' in result) {
timerValue += interval;
setTimeout(onTick, interval);
}
else if ('data' in result) resolve(result.data);
else reject('Unknown polling result!');
} catch (ex) {
reject(ex);
}
}
setTimeout(onTick, timerValue);
});
// Example of usage
let counter = 0;
const result = await polling(async() => {
counter++
if (counter < 4) return { pending: true };
if (counter == 5) throw new Error('Something wrong!');
return { data: 'Success result!' };
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment