Is it a good idea to use requestAnimationFrame within a debounce function?
Asked Answered
S

1

10

This is a check on my understanding of requestAnimationFrame. I have a need for a debounce function, as I'm doing some DOM interaction every time the window is resized and I don't want to overload the browser. A typical debounce function will only call the passed function once per interval; the interval is usually the second argument. I'm assuming that for a lot of UI work, the optimum interval is the shortest amount of time that doesn't overload the browser. It seems to me that that's exactly what requestAnimationFrame would do:

var debounce = function (func, execAsap) {
   var timeout;

  return function debounced () {
    var obj = this, args = arguments;
    function delayed () {
      if (!execAsap)
        func.apply(obj, args);
      timeout = null; 
    };

    if (timeout)
      cancelAnimationFrame(timeout);
    else if (execAsap)
      func.apply(obj, args);

    timeout = requestAnimationFrame(delayed); 
  };
}

The above code is a direct rip-off from the above debounce link, but with requestAnimationFrame used instead of setTimeout. In my understanding, this will queue up the passed-in function as soon as possible, but any calls coming in faster than the browser can handle will get dropped. This should produce the smoothest possible interaction. Am I on the right track? Or am I misunderstanding requestAnimationFrame?

(Of course this only works on modern browsers, but there are easy polyfills for requestAnimationFrame that just fall back to setTimeout.)

Sauger answered 31/3, 2015 at 1:38 Comment(3)
If it's about redrawing, and you want a smooth animation, you want throttling not debouncing. Please re-read the blog post you've linked to see what the difference is - debounce is not "calling the passed function once per interval"Adaptable
@Adaptable thanks for that. I did think about that the first time through, but I revisited it, and read through Ben Alman's notes on the differences benalman.com/projects/jquery-throttle-debounce-plugin, and I think you might be right - though, I think with a fast browser that can respond quickly, it minimizes the difference between the two.Sauger
Was thinking the same thing. So glad I found this post. It would be a good idea to add a context parameter to be used instead of var obj = this. That way people will not have to use bind before calling and saves creating one more function scopeTensive
U
2

This will work.

It has a caveat that may or may not be important to you:

If the page is not currently visible, animations on that page can be throttled heavily so that they do not update often and thus consume little CPU power.

So if you for some reason care about this for the function you are debouncing, you are better off using setTimeout(fn, 0)

Otherwise if you are using this for animations, this is the intended usage of requestAnimationFrame

Ulysses answered 31/3, 2015 at 1:53 Comment(1)
that makes a lot of sense for my particular case- I'm doing some DOM interaction on the resize event, and if my tab isn't active, I'm ok with that interaction not happening until the user switches back to my tab.Sauger

© 2022 - 2024 — McMap. All rights reserved.