1
0
silverbullet/plug-api/lib/async.ts

92 lines
2.2 KiB
TypeScript
Raw Normal View History

2023-08-29 19:17:29 +00:00
export function throttle(func: () => void, limit: number) {
let timer: any = null;
return function () {
if (!timer) {
timer = setTimeout(() => {
func();
timer = null;
}, limit);
}
};
}
// race for promises returns first promise that resolves
export function race<T>(promises: Promise<T>[]): Promise<T> {
return new Promise((resolve, reject) => {
for (const p of promises) {
p.then(resolve, reject);
}
});
}
export function timeout(ms: number): Promise<never> {
return new Promise((_resolve, reject) =>
setTimeout(() => {
reject(new Error("timeout"));
}, ms)
);
}
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export class PromiseQueue {
private queue: {
fn: () => Promise<any>;
resolve: (value: any) => void;
reject: (error: any) => void;
}[] = [];
private processing = false;
2023-08-29 19:17:29 +00:00
runInQueue(fn: () => Promise<any>): Promise<any> {
return new Promise((resolve, reject) => {
this.queue.push({ fn, resolve, reject });
if (!this.processing) {
this.process();
2023-08-29 19:17:29 +00:00
}
});
}
private async process(): Promise<void> {
2023-08-29 19:17:29 +00:00
if (this.queue.length === 0) {
this.processing = false;
2023-08-29 19:17:29 +00:00
return;
}
this.processing = true;
2023-08-29 19:17:29 +00:00
const { fn, resolve, reject } = this.queue.shift()!;
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
this.process(); // Continue processing the next promise in the queue
2023-08-29 19:17:29 +00:00
}
}
export async function batchRequests<I, O>(
values: I[],
fn: (batch: I[]) => Promise<O[]>,
batchSize: number,
): Promise<O[]> {
const results: O[] = [];
// Split values into batches of batchSize
const batches: I[][] = [];
for (let i = 0; i < values.length; i += batchSize) {
batches.push(values.slice(i, i + batchSize));
}
// Run fn on them in parallel
const batchResults = await Promise.all(batches.map(fn));
// Flatten the results
for (const batchResult of batchResults) {
if (Array.isArray(batchResult)) { // If fn returns an array, collect them
results.push(...batchResult);
}
}
return results;
}