import { fork } from " @/helpers/fork.ts " ;
import { list } from " @/helpers/list.ts " ;
import { sort } from " @/helpers/sort.ts " ;
import { tryit } from " @/helpers/tryit.ts " ;
type WorkItemResult < K > = {
* Executes many async functions in parallel. Returns the results from
* all functions as an array. After all functions have resolved, if
* any errors were thrown, they are rethrown in an instance of
* // Process images concurrently, resizing each image to a standard size.
* const images = await parallel(2, imageFiles, async (file) => {
* return await resizeImage(file)
export async function parallel < T , K > (
func : ( item : T ) => Promise < K >,
const work = array . map ( ( item , index ) => ( {
const processor = async ( res : ( value : WorkItemResult < K > [] ) => void ) => {
const results : WorkItemResult < K > [] = [] ;
const [ error , result ] = await tryit ( func )( next . item ) ;
const queues = list ( 1 , limit ) . map ( () => new Promise ( processor ));
// Wait for all queues to complete
const itemResults = ( await Promise . all ( queues )) as WorkItemResult < K > [][];
const [ errors , results ] = fork (
sort ( itemResults . flat () , ( r ) => r . index ) ,
throw new AggregateError ( errors . map ( ( error ) => error . error ));
return results . map ( ( r ) => r . result );