Created
June 13, 2016 11:28
-
-
Save FLamparski/9b1e742ea00175895bfb9810d7c3cf63 to your computer and use it in GitHub Desktop.
A rate-limiting queue for promised jobs
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
const _ = require('lodash') | |
/** | |
* A rate-limiting queue for functions that return promises. | |
* | |
* const q = new Queue({rate: 1000}) | |
* Promise.all(_.range(10).map(n => q.push(() => n * n))).then(all => console.log(all)) | |
* q.start() | |
* // ten seconds later => [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ] | |
* | |
* const q = new Queue({rate: 125}) // try to not exceed 500 requests in 60 seconds | |
* Promise.all(bunchOfPeople.map(p => intercom.getUser(p))).then(intercomUsers => ...) | |
* q.start() | |
* | |
* The rate limiter is based on setInterval(). You can stop the queue with | |
* queue.stop(). This will cancel the interval immediately and any pending jobs | |
* will not run until you call queue.start() again. | |
*/ | |
class Queue { | |
constructor(options) { | |
this.opts = _.defaults(options, { | |
rate: 100 | |
}) | |
this.jobs = [] | |
} | |
start() { | |
if (this.timer) return | |
this.timer = setInterval(() => this._next(), this.opts.rate) | |
} | |
stop() { | |
if (!this.timer) return | |
clearInterval(this.timer) | |
this.timer = null | |
} | |
_next() { | |
const job = this.jobs.shift() | |
if (job) job() | |
} | |
push(job) { | |
return new Promise((resolve, reject) => { | |
this.jobs.push(() => Promise.resolve(job()).then(resolve).catch(reject)) | |
}) | |
} | |
} | |
module.exports = Queue |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment