0

I am developing a custom scrollbar, and for performance reasons I want to add debounce to a mousemove event. The problem is the event object doesn't get passed to the handler and I get undefined.

here is what i wanna do:

function myFunc (a, b, event) {some code}
element.on('mousemove' , debounce(myfunc));

doesn't work! I also tried:

let myDBFunc = debounce(myFunc, 200)
element.on('mousemove', function(event){
    myDBFunc(a, b, event);
});

nothing! any ideas?

UPDATE: the debounce function:

function debounce(func, wait = 20,immediate = true){
    let timeout;
    return function() {
        let context = this, args = arguments;
        let later = function () {
            timeout = null;
            if(!immediate) func.apply(context, args);
        };
        let callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context.args) ; //edited to func.apply(context, args);
    };
}
Eclipse-
  • 51
  • 3
  • 11

1 Answers1

0

It does not work because the a, b arguments are not passed, and the event object gets passed as first argument. You could pass all three of them via an anonymous function, like this:

element.on('mousemove' , (e) => debounce(myfunc)(a, b, e));

Also, after you provided the debounce function, it turns out there is an error in that function near the end. Change:

func.apply(context.args)

to:

func.apply(context, args)

Furthermore, that debounce function will call nothing when you use the default arguments, or even when you provide a nonzero wait argument and true for immediate. It will work better when you change:

if(!immediate) func.apply(context, args);

to:

if(!callNow) func.apply(context, args);

Demo

For your purpose I would use this debounce function. See demo below with the extra arguments:

function debounce(func, wait = 200) {
    let timeout;
    
    return function(...args) { 
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            timeout = setTimeout(() => timeout = null, wait);
            func.apply(this, args);
        }, timeout ? wait : 0);
    };
}

const element = $('div');

function myfunc(a, b, e) {
    console.log(a, b, e.target.tagName, performance.now());
}

const f = debounce(myfunc);
let a = 1, b = 2;
element.on('mousemove' , (e) => f(a, b, e));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>move mouse here</div>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I tried you solution, even when I eliminate other arguments I get undefined event: `function myFunc (e) { console.log(e); } element.on('mousemove', (e) => debounce(myFunc)(e));` still e is undefined. – Eclipse- Jul 10 '19 at 10:33
  • See addition to my answer. There is a bug in your `debounce` function. – trincot Jul 10 '19 at 10:38
  • Thank you for your time. yeah, my bad, I fixed it. I tried your solotion, I dont get undefined anymore. But the problem is, the debounce function is now doing nothing, no matter how I change `wait`, my function still fires a thousand times per second. I think your piece of code is equivalent of using an anonymous function. I have tried that approach, and the event fires the anonymous function, so it does not get debounced. – Eclipse- Jul 10 '19 at 11:02
  • The `immediate` argument is by default `true`, which means it will call the function immediately and never asynchronously. Did you try with `immediate = false`? Where did you get this `debounce` function from? It is quite strange in how it deals with `immediate`.... Because as you experience, if `immediate` is true and `wait` nonzero, there is nothing being called, ...ever. And yet, these are the default values for those arguments. – trincot Jul 10 '19 at 11:11
  • I just tried this code: `function print (e) {console.log(e);} element.on('mousemove', debounce(print))`. It is working as expected. I found this on first google result on debounce function, [link](https://davidwalsh.name/javascript-debounce-function) – Eclipse- Jul 10 '19 at 11:19
  • See yet another addition to my answer. See also [this Q&A](https://stackoverflow.com/questions/24004791/can-someone-explain-the-debounce-function-in-javascript) which addresses this issue also. – trincot Jul 10 '19 at 11:23
  • Yes it is different. to test this one, I replaced my debounce with the one mentioned in the Q&A, they both exhibit the same kind of behavior. With that in mind, my problem still persists. If i wrap my debounce (any of these two) in an anonymous function to be able to pass args(beside event object) to it, it has no effect. If I only pass the event object(which is done automatically), the both work! – Eclipse- Jul 10 '19 at 11:36
  • I have trouble following you. Could you link to a fiddle that demonstrates what you are trying and describe what is not going as you want it? – trincot Jul 10 '19 at 11:40
  • NB: I see you corrected in your question the error I had pointed out concerning `context.args`. Now that part of my answer looks stupid. Please revert that back to how you had it first. – trincot Jul 10 '19 at 12:01
  • See the demo I added to my answer. – trincot Jul 10 '19 at 12:08