UNPKG

@forivall/wyt

Version:

A time-based rate limiter using promises

54 lines (43 loc) 1.45 kB
function sleep(ms: number): Promise<void> { return new Promise((resolve) => { setTimeout(() => resolve(), ms); }); } type State = { lastReload: number; availableRequests: number; }; function reload(requestsPerInterval: number, interval: number, state: State): State { const throughput = requestsPerInterval / interval; const now = Date.now(); const reloadTime = now - state.lastReload; const reloadedRequests = reloadTime * throughput; const newAvalableRequests = state.availableRequests + reloadedRequests; return { ...state, lastReload: now, availableRequests: Math.min(newAvalableRequests, requestsPerInterval), }; } export = function wyt( requestsPerInterval: number, interval: number, ): (requests?: number) => Promise<number> { const timePerRequest = interval / requestsPerInterval; let state: State = { lastReload: Date.now(), availableRequests: requestsPerInterval, }; async function waitRequest(requests = 1): Promise<number> { if (requests > requestsPerInterval) { throw new Error('Requests can not be greater than the number of requests per interval'); } state = reload(requestsPerInterval, interval, state); const requestsToWait = Math.max(0, requests - state.availableRequests); const wait = Math.ceil(requestsToWait * timePerRequest); state.availableRequests -= requests; await sleep(wait); return wait; } return waitRequest; }