Created
November 7, 2016 21:11
-
-
Save moodysalem/08cbf799465b6f147adf282fac0dac13 to your computer and use it in GitHub Desktop.
JS function that calls a set of functions that generate promises (called generators) in batches and resolves when they have all completed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _ from 'underscore'; | |
/** | |
* Takes an array of generators, i.e. functions that return promises, and calls them such that there are only ever | |
* 5 requests that are waiting on responses. Returns a promise that resolves to all the resulting promises only after | |
* they have all been executed | |
* | |
* @param generators array of functions that | |
* @param batchSize max number of requests to execute at a time | |
* @param throttle how often the queue is checked for more requests to process | |
*/ | |
export default function queuePromises(generators, { batchSize = 5, throttle = 100 } = {}) { | |
if (!_.isArray(generators)) { | |
return Promise.reject(new Error('Invalid argument generators: must be an array')); | |
} | |
if (!_.all(generators, fn => typeof fn == 'function')) { | |
return Promise.reject(new Error('Invalid set of generators: one or more were not functions')); | |
} | |
return new Promise(resolve => { | |
// this is the array we will shift items off of | |
const queued = [ ...generators ], | |
// this is the set of promises that have finished | |
done = []; | |
let inProgress = []; | |
// we will throttle how often we push from queued to in progress | |
const processMore = _.throttle(() => { | |
if (queued.length == 0) { | |
resolve(Promise.all(done.concat(inProgress))); | |
return; | |
} | |
// remove the generators we should trigger | |
const more = queued.splice(0, batchSize - inProgress.length); | |
// trigger the calls and add them to in progress | |
inProgress = inProgress.concat( | |
more.map(fn => { | |
// create the promise | |
const prom = fn(); | |
// when it finishes, push it to the stack of done, remove it from inProgress | |
prom.finally(() => { | |
done.push(prom); | |
inProgress = _.without(inProgress, prom); | |
// add more to in progress | |
processMore(); | |
}); | |
return prom; | |
}) | |
); | |
}, throttle); | |
processMore(); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment