I need a simple debounce function with immediate always true.
Without resorting to lodash and with the help of Can someone explain the "debounce" function in Javascript , I implemented it as following,
function debounce(func, wait) {
var timeout;
return function() {
if (!timeout) func.apply(this, arguments);
clearTimeout(timeout);
timeout = setTimeout(()=>{timeout = null}, wait);
};
};
It works as expected until I need to debounce axios request. Assumed I have a debounced axios method, I would like the calling method to be as usual, which means my debounced axios method should return promise I believe.
//the calling method should not change
debounced_axios().then(res => {...}).catch(err => {...})
The essence of original debounce implementation is to just run func once in a wait timeframe, but how do I just return one promise in a wait timeframe ?
Then I came up with the following solution
all_timers = {}
function debounce_axios(input, wait) {
return new Promise((resolve, reject) => {
let timer = all_timers.[input] //check if it is a repeated request, pseudo code
if (!timer) {
axios(input).then(res=>{
resolve(res)
}).catch(err => {
reject(err)
})
}
clearTimeout(timer);
timer = setTimeout(()=>{timer = null}, wait);
all_timers[input] = timer
};
};
So the essence of my debounce_axios is to let the promise stay in pending state for the repeated request.Then the calling method debounced_axios().then(res => {...}).catch(err => {...})
does not need to change.
The answer here Are JavaScript forever-pending promises bad? said "There should be no side effect."
But I am still not 100% sure about letting a promise stay in pending forever.
The other question is that Promise Anti patterns suggested not creating unnecessary promise. But in my case creating a new promise seems necessary.
In a nutshell is there a simple to way to debounce axios request (or any request returns promise) ?
In essence, you need to share result of your debounce function. In your case, thats a promise:
I agree that it's not a good idea. A better approach would be to move the entire promise chain inside the debounced function.
Another option would be to return a cached value when the debounced call does not trigger a new request. This would solve your problem that you always need to return a promise:
Of course that would mean that in some cases, multiple
then
handlers will be called when your request finishes. It depends on your application whether that is a problem or just superfluous work.Only one promise is necessary: when you create the never-resolved one. You can write that as
Or at least avoid the
.then(resolve).catch(reject)
part. Better writeAnd should you consider to reject the promise in case that the timeout has not yet occurred (so that the calling code can handle the rejection), you don't need
new Promise
either: