"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ratelimit = exports.until = exports.delay = void 0;
const timers_1 = __importDefault(require("timers"));
function delay(millis, unref = false) {
    return new Promise((resolve) => {
        const t = timers_1.default.setTimeout(() => resolve(), millis);
        if (unref)
            t.unref();
    });
}
exports.delay = delay;
/**
 * Run the given thunk until the promise is resolved to true, or the timeout
 * passes.
 */
async function until(f, timeoutMs, delayMs = 50) {
    const timeoutAt = Date.now() + timeoutMs;
    let count = 0;
    while (Date.now() < timeoutAt) {
        if (await f(count)) {
            return true;
        }
        else {
            count++;
            await delay(delayMs);
        }
    }
    return false;
}
exports.until = until;
/**
 * @return a thunk that will call the underlying thunk at most every `minDelayMs`
 * milliseconds. The thunk will accept a boolean, that, when set, will force the
 * underlying thunk to be called (mostly useful for tests)
 */
function ratelimit(f, minDelayMs) {
    let next = 0;
    return (force) => {
        if (Date.now() > next || force === true) {
            next = Date.now() + minDelayMs;
            return f();
        }
        else {
            return;
        }
    };
}
exports.ratelimit = ratelimit;
//# sourceMappingURL=Async.js.map