68 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			68 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
module.exports = (iterable, mapper, opts) => new Promise((resolve, reject) => {
 | 
						|
	opts = Object.assign({
 | 
						|
		concurrency: Infinity
 | 
						|
	}, opts);
 | 
						|
 | 
						|
	if (typeof mapper !== 'function') {
 | 
						|
		throw new TypeError('Mapper function is required');
 | 
						|
	}
 | 
						|
 | 
						|
	const concurrency = opts.concurrency;
 | 
						|
 | 
						|
	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 iterator = iterable[Symbol.iterator]();
 | 
						|
	let isRejected = false;
 | 
						|
	let iterableDone = false;
 | 
						|
	let resolvingCount = 0;
 | 
						|
	let currentIdx = 0;
 | 
						|
 | 
						|
	const next = () => {
 | 
						|
		if (isRejected) {
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		const nextItem = iterator.next();
 | 
						|
		const i = currentIdx;
 | 
						|
		currentIdx++;
 | 
						|
 | 
						|
		if (nextItem.done) {
 | 
						|
			iterableDone = true;
 | 
						|
 | 
						|
			if (resolvingCount === 0) {
 | 
						|
				resolve(ret);
 | 
						|
			}
 | 
						|
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		resolvingCount++;
 | 
						|
 | 
						|
		Promise.resolve(nextItem.value)
 | 
						|
			.then(el => mapper(el, i))
 | 
						|
			.then(
 | 
						|
				val => {
 | 
						|
					ret[i] = val;
 | 
						|
					resolvingCount--;
 | 
						|
					next();
 | 
						|
				},
 | 
						|
				err => {
 | 
						|
					isRejected = true;
 | 
						|
					reject(err);
 | 
						|
				}
 | 
						|
			);
 | 
						|
	};
 | 
						|
 | 
						|
	for (let i = 0; i < concurrency; i++) {
 | 
						|
		next();
 | 
						|
 | 
						|
		if (iterableDone) {
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
});
 |