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