Skip to content

Instantly share code, notes, and snippets.

@alaindet
Created July 15, 2025 08:57
Show Gist options
  • Save alaindet/48788abfda407660630ff64f5d389203 to your computer and use it in GitHub Desktop.
Save alaindet/48788abfda407660630ff64f5d389203 to your computer and use it in GitHub Desktop.
class DoubleArrayQueue<T> {
inElements: T[] = [];
outElements: T[] = [];
enqueue(element: T) {
this.inElements.push(element);
}
dequeue() {
this.transferElements();
if (this.outElements.length === 0) {
return null;
}
return this.outElements.pop();
}
peek() {
this.transferElements();
if (this.outElements.length === 0) {
return null;
}
return this.outElements[0];
}
size() {
return this.inElements.length + this.outElements.length;
}
isEmpty() {
return this.size() === 0;
}
private transferElements() {
if (this.inElements.length === 0 || this.outElements.length > 0) {
return;
}
for (let i = 0, len = this.inElements.length; i < len; i++) {
const element = this.inElements.pop()!;
this.outElements.push(element);
}
}
}
class PromisesPool {
private poolSize = 5;
private runningTasks = 0;
private queue = new DoubleArrayQueue<() => void>();
// private queue: (() => void)[] = [];
setSize(size: number) {
this.poolSize = size;
}
enqueue<T>(promiseFn: () => Promise<T>): Promise<T> {
return new Promise<T>((resolve, reject) => {
const task = async () => {
this.runningTasks++;
try {
resolve(await promiseFn());
} catch (error) {
reject(error);
} finally {
this.runningTasks--;
this.runNext();
}
};
if (this.runningTasks < this.poolSize) {
task();
} else {
this.queue.enqueue(task);
// this.queue.push(task);
}
});
}
private runNext() {
if (this.queue.size() === 0 || this.runningTasks >= this.poolSize) {
return;
}
const nextTask = this.queue.dequeue();
if (nextTask) {
nextTask();
}
}
}
// Test code
function createFakeHttpRequest(id: string, delay: number) {
return new Promise(done => setTimeout(() => done(`Response ${id}`), delay));
}
function range(from: number, to: number): number[] {
let result: number[] = [];
for (let i = from; i <= to; i++) {
result.push(i);
}
return result;
}
async function run() {
const pool = new PromisesPool();
pool.setSize(3);
range(1, 50).forEach(n => {
pool.enqueue(() => createFakeHttpRequest(`${n}`, 500)).then(console.log);
});
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment