Skip to content

Instantly share code, notes, and snippets.

@scwood
Last active March 6, 2018 23:01
Show Gist options
  • Select an option

  • Save scwood/c260f3129999c124cec6e828ac4a0ba7 to your computer and use it in GitHub Desktop.

Select an option

Save scwood/c260f3129999c124cec6e828ac4a0ba7 to your computer and use it in GitHub Desktop.
Limiting concurrency of a module with a JavaScript Proxy
// Imagine some library that does stuff.
const library = {
makeApiCall,
};
function makeApiCall() {
return new Promise((resolve, reject) => {
console.log('starting...');
setTimeout(() => {
console.log('...finishing');
resolve('done!')
}, 1000);
})
}
// You would like to limit the concurrency of this library. One wa to do
// this is via a Proxy object that can intercept function calls in order to
// manipulate the behavior.
//
// In this case, when a function is called on the original library object, we'll
// replace it's behavior to not call the function directly and to instead push a thunk
// of that function into some queueing library like the theoretical one below
const PromiseQueue = require('./PromiseQueue');
function queueAllFunctionCalls(obj, {concurrency = 1} = {}) {
return new Proxy(obj, {
queue: new PromiseQueue({concurrency}),
get(target, name) {
const origMethod = target[name];
return (...args) => {
return this.queue.push(() => origMethod.apply(this, args));
}
}
})
}
const wrappedLibrary = queueAllFunctionCalls(library, {concurrency: 2});
// you then export this "wrapped" version of library. To the user the API
// remains unchanged, but under the hood the concurrency is being limited
for (let i = 0; i < 5; i++) {
wrappedLibrary.makeApiCall()
.then(console.log)
.catch(console.error)
}
// Above, we kick off five calls, but only two are executed at a time until all
// five are made.
//
// Huzzah!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment