'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; } } });