Last active
March 24, 2017 18:08
-
-
Save mazesoul/0b9319a2cc30d171b4cb00783d0bd93c to your computer and use it in GitHub Desktop.
Debounced promise with multiple context
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
/** | |
* Laurent Villleneuve 2017-03-24 | |
* https://github.com/mazesoul | |
* | |
* Uses Q.js but should be transposable. | |
* | |
* Debounces the execution of a function, not by time but by its returning promise | |
* | |
* 1. On first call, invoke the <debounced> function, store and return its promise. | |
* 2. Subsequent calls return the first call's promise | |
* 3. When the first call promise is resolved, the debouncing context is over. (Instead of a timeout) | |
* | |
* This allows multiple concurrent calls to rely on the successful execution of a single method. | |
* | |
* Example: | |
* | |
* If multiple calls come in that all require a default value. And this value generation has some lag (db state). | |
* When the calls are initiated, they all cannot find the default value. Consequently they all attempt to create it. | |
* This lead to multiple instances of a default value which is undesirable. | |
* (Or, to failures if duplication constraints are in place) | |
* | |
* This wrapper ensures that only the first caller invokes the default value generation. | |
* Subsequent calls return the first call's promise without duplicating the execution. | |
* | |
* | |
* @param {function} options.concurrencyId A function that generates a concurrencyId to identify concurrent calls. | |
* The function is invoked with the same arguments as <debounced>. | |
* PS: The same function could be necessary in multiple context that are not concurrent. (Multiple tenants) | |
* @param {[type]} options.debounced A function that returns a promise and needs to be debounced. | |
* @return {[type]} [description] | |
*/ | |
function debouncedPromise({concurrencyId,debounced}) { | |
const pendings = new Map(); | |
return (...args) => { | |
const key = concurrencyId(...args); | |
if (pendings.has(key)) { | |
return pendings.get(key); | |
} | |
const deferred = Q.defer(); | |
pendings.set(key, deferred.promise); | |
deferred.resolve(debounced(...args)); | |
return deferred.promise.finally(() => pendings.delete(key)); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment