@@ -46,17 +46,57 @@ const GREEN = "\x1b[92m";
4646const RED = "\x1b[91m" ;
4747const RESET = "\x1b[0m" ;
4848
49+ /**
50+ * Maps over an array of items with a concurrency limit, applying an asynchronous mapper function to each item.
51+ *
52+ * @template T - The type of the items in the input array.
53+ * @template O - The type of the items in the output array.
54+ *
55+ * @param {T[] } iterable - The array of items to be mapped.
56+ * @param {(item: T) => Promise<O> } mapper - The asynchronous function to apply to each item.
57+ * @param {{ concurrency: number } } options - Options for the mapping operation.
58+ * @param {number } options.concurrency - The maximum number of promises to resolve concurrently.
59+ *
60+ * @returns {Promise<O[]> } A promise that resolves to an array of mapped items.
61+ *
62+ * @throws {TypeError } If the first argument is not an array.
63+ * @throws {TypeError } If the second argument is not a function.
64+ * @throws {TypeError } If the concurrency option is not a positive number.
65+ *
66+ * @description
67+ * The `pMap` function processes the input array in chunks, where the size of each chunk is determined by the `concurrency` option.
68+ * This controls how many promises are resolved at a time, which can help avoid issues such as rate limit errors when making server requests.
69+ */
4970async function pMap < T , O > (
50- iterable : Array < T > ,
51- mapper : ( obj : T ) => Promise < O > ,
52- { concurrency } : { concurrency : number } ,
53- ) : Promise < Array < O > > {
54- const result : Array < O > = [ ] ;
55- result: for ( let i = 0 ; i < iterable . length ; i += concurrency ) {
71+ iterable : T [ ] ,
72+ mapper : ( item : T ) => Promise < O > ,
73+ options : { concurrency : number } ,
74+ ) : Promise < O [ ] > {
75+ const { concurrency } = options ;
76+
77+ if ( ! Array . isArray ( iterable ) ) {
78+ throw new TypeError ( "Expected the first argument to be an array" ) ;
79+ }
80+
81+ if ( typeof mapper !== "function" ) {
82+ throw new TypeError ( "Expected the second argument to be a function" ) ;
83+ }
84+
85+ if ( typeof concurrency !== "number" || concurrency <= 0 ) {
86+ throw new TypeError ( "Expected the concurrency option to be a positive number" ) ;
87+ }
88+
89+ const result : O [ ] = [ ] ;
90+ for ( let i = 0 ; i < iterable . length ; i += concurrency ) {
5691 const chunk = iterable . slice ( i , i + concurrency ) ;
57- const promises = chunk . map ( mapper ) ;
58- const awaitedChunk = await Promise . all ( promises ) ;
59- result . push ( ...awaitedChunk ) ;
92+ try {
93+ const chunkResults = await Promise . all ( chunk . map ( mapper ) ) ;
94+ result . push ( ...chunkResults ) ;
95+ } catch ( error ) {
96+ // Handle individual chunk errors if necessary
97+ // For now, rethrow to reject the entire pMap promise
98+ throw error ;
99+ }
60100 }
61101 return result ;
62102}
0 commit comments