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.
67 lines
1.2 KiB
67 lines
1.2 KiB
'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; |
|
} |
|
} |
|
});
|
|
|