Skip to content

Instantly share code, notes, and snippets.

@FLamparski
Created June 13, 2016 11:28
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 FLamparski/9b1e742ea00175895bfb9810d7c3cf63 to your computer and use it in GitHub Desktop.
Save FLamparski/9b1e742ea00175895bfb9810d7c3cf63 to your computer and use it in GitHub Desktop.
A rate-limiting queue for promised jobs
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