Skip to content

Instantly share code, notes, and snippets.

@tomfun
Last active September 18, 2017 09:13
Show Gist options
  • Save tomfun/8dd8063123f548d5a8b214ebd15bcfa5 to your computer and use it in GitHub Desktop.
Save tomfun/8dd8063123f548d5a8b214ebd15bcfa5 to your computer and use it in GitHub Desktop.
It is analog of [Bluebird.map with concurency](http://bluebirdjs.com/docs/api/promise.map.html) But with [correct start order](https://github.com/petkaantonov/bluebird/issues/847).
function ownMap(arr, cb, {concurrency} = {}) {
if (!concurrency || concurrency < 1) {
return ownMap(arr, cb, {concurrency: Number.POSITIVE_INFINITY})
}
const arrLength = arr.length;
const batchPromises = new Array(arrLength);
let currentTaskNumber = 0;
return new Promise((resolve, reject) => {
function endOneMore(result) {
if (currentTaskNumber === arrLength) {
Promise.all(batchPromises)
.then(resolve);
}
if (currentTaskNumber < arrLength) {
startOneMore();
}
return result;
}
function startOneMore() {
batchPromises[currentTaskNumber] = cb(arr[currentTaskNumber])
.then(endOneMore, reject);
currentTaskNumber++;
}
arr.slice(0, concurrency)
.map((v, i) => startOneMore(i));
});
}
// test
const array = (new Array(10)).fill(0).map((v, k) => k);
ownMap(
array,
(numb) => {
console.error(numb, 'started', numb);
const time = Math.round(Math.random() * 900) + 100;
return (new Promise(resolve => setTimeout(resolve, time)))
// .then(() => console.error(numb, 'ended', numb))
.then(() => `${numb} - ${time}`);
},
{concurrency: 3}
).then((arr) => console.log('finished all', arr.length, arr));
0 'started' 0
1 'started' 1
2 'started' 2
3 'started' 3
4 'started' 4
5 'started' 5
6 'started' 6
7 'started' 7
8 'started' 8
9 'started' 9
finished all 10 [ '0 - 284',
'1 - 327',
'2 - 316',
'3 - 900',
'4 - 643',
'5 - 167',
'6 - 708',
'7 - 622',
'8 - 870',
'9 - 536' ]
@tomfun
Copy link
Author

tomfun commented Sep 18, 2017

interface IAsyncMapWorker<TArg, TRes>{
    (arg: TArg): Promise<TRes>;
}

interface IAsyncMap<TArg, TRes>{
    (
        array: TArg[],
        callback: IAsyncMapWorker<TArg, TRes>,
        numberOfWorkers: number
    ): Promise<TRes[]>;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment