mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-04-29 04:00:09 +00:00
233 lines
6.2 KiB
JavaScript
233 lines
6.2 KiB
JavaScript
// src/utils/promises.tsx
|
|
import { KnownError } from "..";
|
|
import { StackAssertionError, captureError, concatStacktraces } from "./errors";
|
|
import { DependenciesMap } from "./maps";
|
|
import { Result } from "./results";
|
|
import { generateUuid } from "./uuids";
|
|
function createPromise(callback) {
|
|
let status = "pending";
|
|
let valueOrReason = void 0;
|
|
let resolve = null;
|
|
let reject = null;
|
|
const promise = new Promise((res, rej) => {
|
|
resolve = (value) => {
|
|
if (status !== "pending") return;
|
|
status = "fulfilled";
|
|
valueOrReason = value;
|
|
res(value);
|
|
};
|
|
reject = (reason) => {
|
|
if (status !== "pending") return;
|
|
status = "rejected";
|
|
valueOrReason = reason;
|
|
rej(reason);
|
|
};
|
|
});
|
|
callback(resolve, reject);
|
|
return Object.assign(promise, {
|
|
status,
|
|
...status === "fulfilled" ? { value: valueOrReason } : {},
|
|
...status === "rejected" ? { reason: valueOrReason } : {}
|
|
});
|
|
}
|
|
var resolvedCache = null;
|
|
function resolved(value) {
|
|
resolvedCache ??= new DependenciesMap();
|
|
if (resolvedCache.has([value])) {
|
|
return resolvedCache.get([value]);
|
|
}
|
|
const res = Object.assign(Promise.resolve(value), {
|
|
status: "fulfilled",
|
|
value
|
|
});
|
|
resolvedCache.set([value], res);
|
|
return res;
|
|
}
|
|
var rejectedCache = null;
|
|
function rejected(reason) {
|
|
rejectedCache ??= new DependenciesMap();
|
|
if (rejectedCache.has([reason])) {
|
|
return rejectedCache.get([reason]);
|
|
}
|
|
const promise = Promise.reject(reason);
|
|
ignoreUnhandledRejection(promise);
|
|
const res = Object.assign(promise, {
|
|
status: "rejected",
|
|
reason
|
|
});
|
|
rejectedCache.set([reason], res);
|
|
return res;
|
|
}
|
|
var neverResolvePromise = pending(new Promise(() => {
|
|
}));
|
|
function neverResolve() {
|
|
return neverResolvePromise;
|
|
}
|
|
function pending(promise, options = {}) {
|
|
const res = promise.then(
|
|
(value) => {
|
|
res.status = "fulfilled";
|
|
res.value = value;
|
|
return value;
|
|
},
|
|
(actualReason) => {
|
|
res.status = "rejected";
|
|
res.reason = actualReason;
|
|
throw actualReason;
|
|
}
|
|
);
|
|
res.status = "pending";
|
|
return res;
|
|
}
|
|
function ignoreUnhandledRejection(promise) {
|
|
promise.catch(() => {
|
|
});
|
|
}
|
|
async function wait(ms) {
|
|
if (!Number.isFinite(ms) || ms < 0) {
|
|
throw new StackAssertionError(`wait() requires a non-negative integer number of milliseconds to wait. (found: ${ms}ms)`);
|
|
}
|
|
if (ms >= 2 ** 31) {
|
|
throw new StackAssertionError("The maximum timeout for wait() is 2147483647ms (2**31 - 1). (found: ${ms}ms)");
|
|
}
|
|
return await new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
async function waitUntil(date) {
|
|
return await wait(date.getTime() - Date.now());
|
|
}
|
|
function runAsynchronouslyWithAlert(...args) {
|
|
return runAsynchronously(
|
|
args[0],
|
|
{
|
|
...args[1],
|
|
onError: (error) => {
|
|
if (KnownError.isKnownError(error) && typeof process !== "undefined" && process.env.NODE_ENV?.includes("production")) {
|
|
alert(error.message);
|
|
} else {
|
|
alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === "development" ? `check the browser console for the full error.` : "report this to the developer."}
|
|
|
|
${error}`);
|
|
}
|
|
args[1]?.onError?.(error);
|
|
}
|
|
},
|
|
...args.slice(2)
|
|
);
|
|
}
|
|
function runAsynchronously(promiseOrFunc, options = {}) {
|
|
if (typeof promiseOrFunc === "function") {
|
|
promiseOrFunc = promiseOrFunc();
|
|
}
|
|
const duringError = new Error();
|
|
promiseOrFunc?.catch((error) => {
|
|
options.onError?.(error);
|
|
const newError = new StackAssertionError(
|
|
"Uncaught error in asynchronous function: " + error.toString(),
|
|
{ cause: error }
|
|
);
|
|
concatStacktraces(newError, duringError);
|
|
if (!options.noErrorLogging) {
|
|
captureError("runAsynchronously", newError);
|
|
}
|
|
});
|
|
}
|
|
var TimeoutError = class extends Error {
|
|
constructor(ms) {
|
|
super(`Timeout after ${ms}ms`);
|
|
this.ms = ms;
|
|
this.name = "TimeoutError";
|
|
}
|
|
};
|
|
async function timeout(promise, ms) {
|
|
return await Promise.race([
|
|
promise.then((value) => Result.ok(value)),
|
|
wait(ms).then(() => Result.error(new TimeoutError(ms)))
|
|
]);
|
|
}
|
|
async function timeoutThrow(promise, ms) {
|
|
return Result.orThrow(await timeout(promise, ms));
|
|
}
|
|
function rateLimited(func, options) {
|
|
let waitUntil2 = performance.now();
|
|
let queue = [];
|
|
let addedToQueueCallbacks = /* @__PURE__ */ new Map();
|
|
const next = async () => {
|
|
while (true) {
|
|
if (waitUntil2 > performance.now()) {
|
|
await wait(Math.max(1, waitUntil2 - performance.now() + 1));
|
|
} else if (queue.length === 0) {
|
|
const uuid = generateUuid();
|
|
await new Promise((resolve) => {
|
|
addedToQueueCallbacks.set(uuid, resolve);
|
|
});
|
|
addedToQueueCallbacks.delete(uuid);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
const nextFuncs = options.batchCalls ? queue.splice(0, queue.length) : [queue.shift()];
|
|
const start = performance.now();
|
|
const value = await Result.fromPromise(func());
|
|
const end = performance.now();
|
|
waitUntil2 = Math.max(
|
|
waitUntil2,
|
|
start + (options.throttleMs ?? 0),
|
|
end + (options.gapMs ?? 0)
|
|
);
|
|
for (const nextFunc of nextFuncs) {
|
|
if (value.status === "ok") {
|
|
nextFunc[0](value.data);
|
|
} else {
|
|
nextFunc[1](value.error);
|
|
}
|
|
}
|
|
};
|
|
runAsynchronously(async () => {
|
|
while (true) {
|
|
await next();
|
|
}
|
|
});
|
|
return () => {
|
|
return new Promise((resolve, reject) => {
|
|
waitUntil2 = Math.max(
|
|
waitUntil2,
|
|
performance.now() + (options.debounceMs ?? 0)
|
|
);
|
|
queue.push([resolve, reject]);
|
|
addedToQueueCallbacks.forEach((cb) => cb());
|
|
});
|
|
};
|
|
}
|
|
function throttled(func, delayMs) {
|
|
let timeout2 = null;
|
|
let nextAvailable = null;
|
|
return async (...args) => {
|
|
while (nextAvailable !== null) {
|
|
await nextAvailable;
|
|
}
|
|
nextAvailable = new Promise((resolve) => {
|
|
timeout2 = setTimeout(() => {
|
|
nextAvailable = null;
|
|
resolve(func(...args));
|
|
}, delayMs);
|
|
});
|
|
return await nextAvailable;
|
|
};
|
|
}
|
|
export {
|
|
createPromise,
|
|
ignoreUnhandledRejection,
|
|
neverResolve,
|
|
pending,
|
|
rateLimited,
|
|
rejected,
|
|
resolved,
|
|
runAsynchronously,
|
|
runAsynchronouslyWithAlert,
|
|
throttled,
|
|
timeout,
|
|
timeoutThrow,
|
|
wait,
|
|
waitUntil
|
|
};
|
|
//# sourceMappingURL=promises.js.map
|