This is a small (~500B minified and compressed) dependency-free library to limit the amount of promises run per unit of time. It is useful for scenarios such as Rest APIs consumption, where we are normally rate-limited to a certain amount of requests per time.
It doesn't have any dependencies. If you are running this on Node.js, you will need to pass whatever Promise library you are using in the constructor.
Then, you add functions to the PromiseThrottle
that, once called, return a Promise
.
The library can be used either server-side or in the browser.
var PromiseThrottle = require('promise-throttle');
/**
* A function that once called returns a promise
* @return Promise
*/
var myFunction = function(i) {
return new Promise(function(resolve, reject) {
// here we simulate that the promise runs some code
// asynchronously
setTimeout(function() {
console.log(i + ": " + Math.random());
resolve(i);
}, 10);
});
};
var promiseThrottle = new PromiseThrottle({
requestsPerSecond: 1, // up to 1 request per second
promiseImplementation: Promise // the Promise library you are using
});
var amountOfPromises = 10;
while (amountOfPromises-- > 0) {
promiseThrottle.add(myFunction.bind(this, amountOfPromises))
.then(function(i) {
console.log("Promise " + i + " done");
});
}
// example using Promise.all
var one = promiseThrottle.add(myFunction.bind(this, 1));
var two = promiseThrottle.add(myFunction.bind(this, 2));
var three = promiseThrottle.add(myFunction.bind(this, 3));
Promise.all([one, two, three])
.then(function(r) {
console.log("Promises " + r.join(", ") + " done");
});
You can specify weight
option for each promise to dynamically adjust throttling depending on
action "heaviness". For example, action with weight = 2
will be throttled as two regular actions. By default weight of all actions is 1.
var regularAction = promiseThrottle.add(performRegularCall());
var heavyAction = promiseThrottle.add(performHeavyCall(), {weight: 2});
You can cancel queued promises using an AbortSignal. For this, pass a signal
option obtained from an AbortController
. Once it is aborted, the promises queued using the signal will be rejected.
If the environment where you are running the code doesn't support AbortController, you can use a polyfill.
var controller = new AbortController();
var signal = controller.signal;
var pt = createPromiseThrottle(10);
pt.addAll([
function() {
return fetch('example.com/a');
},
function() {
return fetch('example.com/b');
},
function() {
...
}
], {signal: signal});
...
// let's abort the promises
controller.abort();
You can decide to make only specific promises abortable:
var controller = new AbortController();
var signal = controller.signal;
var pt = createPromiseThrottle(10);
pt.add(function() { return fetch('example.com/a') });
pt.add(function() { return fetch('example.com/b') }, {signal: signal});
pt.add(function() { return fetch('example.com/c') });
...
// let's abort the second one
controller.abort();
When aborting, the promise returned by add
or addAll
is rejected with a specific error:
var controller = new AbortController();
var signal = controller.signal;
var pt = createPromiseThrottle(10);
pt.addAll([
function() {
return fetch('example.com/a');
},
function() {
return fetch('example.com/b');
},
function() {
...
}
], {signal: signal}).catch(function(e) {
if (e.name === 'AbortError') {
console.log('Promises aborted');
}
});
...
// let's abort the promises
controller.abort();
For node.js, install the module with: npm i promise-throttle
If you are using it in a browser, you can use bower: bower install promise-throttle
Install the dependencies using npm install
.
Run npm start
to lint, test and browserify promise-thottle.
See how some projects are using it:
- ivasilov/promised-twitter
- JMPerez/spotify-dedup
- johannesss/randify
- JoseBarrios/mturk-api
- zackiles/lucy-bot
MIT