Created
July 20, 2021 06:47
-
-
Save james4388/371503a5bd67aeb4cf5cb26467974752 to your computer and use it in GitHub Desktop.
Map in parallel and only allow to run with concurrencyLimit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type InputWithIndex<I> = [I, number]; | |
async function parallelMap<I, O>(inputs: I[], asyncMapper: (...input: I[]) => O, concurrencyLimit: number = 5): Promise<O[]> { | |
concurrencyLimit = Math.max(1, concurrencyLimit); | |
const inputStack: InputWithIndex<I>[] = inputs.map((input: I, index: number): InputWithIndex<I> => [input, index]).reverse(); | |
const results = new Array(inputs.length).fill(undefined); | |
const workers = new Array(concurrencyLimit).fill(undefined); | |
async function work() { | |
if (inputStack.length) { | |
const [input, originalIndex]: InputWithIndex<I> = inputStack.pop(); | |
let result; | |
if (Array.isArray(input)) { | |
result = await asyncMapper(...input); | |
} else { | |
result = await asyncMapper(input); | |
} | |
results[originalIndex] = result; | |
return work(); | |
} | |
return Promise.resolve(); | |
} | |
await Promise.all(workers.map(work)); | |
return results; | |
} | |
// Test code; | |
let counter = 0; | |
let interval = 0; | |
async function doulbeMapper(input: number) { | |
return new Promise((resolve, reject) => { | |
counter += 1; | |
setTimeout(() => { | |
counter -= 1; | |
resolve(input * 2); | |
}, Math.random() * 3000); | |
}) | |
} | |
const watchCounter = () => { | |
console.log('Promises running in the beginning:', counter); | |
if (interval) { | |
clearInterval(interval); | |
} | |
interval = setInterval(() => console.log('Promises running:', counter), 1000); | |
}; | |
(async () => { | |
watchCounter(); | |
const arr = await parallelMap([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], doulbeMapper, 4); | |
console.log(arr); | |
clearInterval(interval); | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment