Skip to content

Instantly share code, notes, and snippets.

@alexanderankin
Last active August 5, 2022 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexanderankin/7245ba393a1d19fb1116b4e4eb668a0e to your computer and use it in GitHub Desktop.
Save alexanderankin/7245ba393a1d19fb1116b4e4eb668a0e to your computer and use it in GitHub Desktop.
how to throttle requests in node
let levels = {
error: 200,
warn: 300,
info: 400,
debug: 500,
trace: 600,
}
let level = levels['info'];
function noop() {
}
let logger = {
error: level >= levels.error ? console.log : noop,
warn: level >= levels.warn ? console.log : noop,
info: level >= levels.info ? console.log : noop,
debug: level >= levels.debug ? console.log : noop,
trace: level >= levels.trace ? console.log : noop,
}
async function main(count) {
logger.info('starting with:', count);
let promises = [];
for (let i = 0; i < count; i++) {
promises.push(request(i));
logger.trace('pushed', i, 'total', promises.length);
if (promises.length >= 10) {
logger.trace('too many in the queue', i)
let { index } = await promiseAny(promises);
logger.debug('removing index:', index, i);
promises.splice(index, 1);
}
}
let results = await Promise.allSettled(promises);
logger.info('DONE')
return results;
}
async function request(arg) {
await new Promise(r => setTimeout(r, ~~(Math.random() * 10_000)));
console.log('done: ', arg);
}
async function promiseAny(iterable) {
return Promise.all(
[...iterable]
.map(function flipErrorCallback(original, index) {
return Promise.resolve({
then(resolve, reject) {
original.then(data => {
logger.trace('hi from promiseAny success', index)
// rejection error is data! this short circuits Promise.all
reject({ data, index })
},
function () {
logger.trace('hi from promiseAny fail', index)
resolve(...arguments);
});
}
});
})
)
.then(
errors => Promise.reject(errors),
value => Promise.resolve(value)
);
}
async function test_promiseAny() {
console.log(await promiseAny([
new Promise(r => setTimeout(() => r(10000), 10000).unref()),
new Promise(r => setTimeout(() => r(15000), 15000).unref()),
new Promise(r => setTimeout(() => r(500), 500)),
]))
}
if (require.main === module) {
main(isNaN(process.argv[2]) ? 200 : parseInt(process.argv[2], 10)).then(console.log);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment