You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							81 lines
						
					
					
						
							1.5 KiB
						
					
					
				
			
		
		
	
	
							81 lines
						
					
					
						
							1.5 KiB
						
					
					
				'use strict'; | 
						|
const AggregateError = require('aggregate-error'); | 
						|
 | 
						|
module.exports = async ( | 
						|
	iterable, | 
						|
	mapper, | 
						|
	{ | 
						|
		concurrency = Infinity, | 
						|
		stopOnError = true | 
						|
	} = {} | 
						|
) => { | 
						|
	return new Promise((resolve, reject) => { | 
						|
		if (typeof mapper !== 'function') { | 
						|
			throw new TypeError('Mapper function is required'); | 
						|
		} | 
						|
 | 
						|
		if (!(typeof concurrency === 'number' && concurrency >= 1)) { | 
						|
			throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); | 
						|
		} | 
						|
 | 
						|
		const ret = []; | 
						|
		const errors = []; | 
						|
		const iterator = iterable[Symbol.iterator](); | 
						|
		let isRejected = false; | 
						|
		let isIterableDone = false; | 
						|
		let resolvingCount = 0; | 
						|
		let currentIndex = 0; | 
						|
 | 
						|
		const next = () => { | 
						|
			if (isRejected) { | 
						|
				return; | 
						|
			} | 
						|
 | 
						|
			const nextItem = iterator.next(); | 
						|
			const i = currentIndex; | 
						|
			currentIndex++; | 
						|
 | 
						|
			if (nextItem.done) { | 
						|
				isIterableDone = true; | 
						|
 | 
						|
				if (resolvingCount === 0) { | 
						|
					if (!stopOnError && errors.length !== 0) { | 
						|
						reject(new AggregateError(errors)); | 
						|
					} else { | 
						|
						resolve(ret); | 
						|
					} | 
						|
				} | 
						|
 | 
						|
				return; | 
						|
			} | 
						|
 | 
						|
			resolvingCount++; | 
						|
 | 
						|
			(async () => { | 
						|
				try { | 
						|
					const element = await nextItem.value; | 
						|
					ret[i] = await mapper(element, i); | 
						|
					resolvingCount--; | 
						|
					next(); | 
						|
				} catch (error) { | 
						|
					if (stopOnError) { | 
						|
						isRejected = true; | 
						|
						reject(error); | 
						|
					} else { | 
						|
						errors.push(error); | 
						|
						resolvingCount--; | 
						|
						next(); | 
						|
					} | 
						|
				} | 
						|
			})(); | 
						|
		}; | 
						|
 | 
						|
		for (let i = 0; i < concurrency; i++) { | 
						|
			next(); | 
						|
 | 
						|
			if (isIterableDone) { | 
						|
				break; | 
						|
			} | 
						|
		} | 
						|
	}); | 
						|
};
 | 
						|
 |