Last active
August 5, 2022 13:59
-
-
Save alexanderankin/7245ba393a1d19fb1116b4e4eb668a0e to your computer and use it in GitHub Desktop.
how to throttle requests in node
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
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