Skip to content

Instantly share code, notes, and snippets.

@dmitry-tuzenkov
Last active December 27, 2023 17:25
Show Gist options
  • Save dmitry-tuzenkov/0ae321d84adae7f79baf2aefaca025d0 to your computer and use it in GitHub Desktop.
Save dmitry-tuzenkov/0ae321d84adae7f79baf2aefaca025d0 to your computer and use it in GitHub Desktop.
type JobFunction<T> = () => Promise<T>;
async function promiseAll<T>(
jobs: JobFunction<T>[],
concurrency: number = Infinity,
): Promise<T[]> {
const results: T[] = new Array(jobs.length).fill(0);
const queue = new Array(concurrency).fill(Promise.resolve());
// const queue = jobs.splice(0, concurrency).map((fn: JobFunction<T>) =>
// fn().then((result: T) => {
// results.push(result);
// console.log("result", result);
// return result;
// }),
// );
for (let index in jobs) {
const newIndex = Number(index) % concurrency;
console.log(index, newIndex);
// [0] => [0] -> [0] -> [0] ->
// [1] => [0] -> [0] -> [0] ->
// queue[newIndex] = queue[newIndex]
queue[newIndex] = Promise.race(queue)
.then((): ReturnType<JobFunction<T>> => {
console.log("queue", index, newIndex);
// if (!jobs.length) {
// return Promise.reject();
// }
const fn = jobs.splice(0, 1)[0];
return fn();
})
.then((result: T) => {
results[index] = result;
console.log("result", result, index);
return result;
});
}
console.log(await Promise.all(queue));
return results;
}
const asyncCall = <T>(ttl: number = 5000, value: T): Promise<T> => {
return new Promise<T>((resolve) => {
setTimeout(() => resolve(value), ttl);
});
};
promiseAll(
[
() => asyncCall(1000, 1), // 1
() => asyncCall(110, 2), // 1
() => asyncCall(120, 3), // 2
() => asyncCall(130, 4), // 2
() => asyncCall(140, 5), // 3
() => asyncCall(150, 6), // 3
() => asyncCall(160, 7), // 4
],
2,
).then(console.log);
type JobFunction<T> = () => Promise<T>;
async function promiseAll<T>(
jobs: JobFunction<T>[],
concurrency: number = Infinity,
): Promise<T[]> {
const queue = new Array(concurrency).fill(Promise.resolve());
const jobsQueue: Promise<T>[] = jobs.map((j) => j());
for (let i = 0; i < jobsQueue.length; i++) {
const index = i % concurrency;
const promise = jobsQueue[i];
queue[index] = Promise.race(queue).then(() => {
console.log("solving job i =", i, "consumer index =", index);
return promise;
});
}
return await Promise.all(jobsQueue);
}
const asyncCall = <T>(ttl: number = 5000, value: T): Promise<T> => {
return new Promise<T>((resolve) => {
setTimeout(() => resolve(value), ttl);
});
};
promiseAll(
[
() => asyncCall(10000, 1), // 1
() => asyncCall(110, 2), // 1
() => asyncCall(120, 3), // 2
() => asyncCall(130, 4), // 2
() => asyncCall(140, 5), // 3
() => asyncCall(150, 6), // 3
() => asyncCall(160, 7), // 4
],
2,
).then(console.log);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment