stutrek / scrollmonitor

A simple and fast API to monitor elements as you scroll
MIT License
3.3k stars 243 forks source link

Allow option for debouncing scroll monitor. #51

Closed Nolski closed 7 years ago

Nolski commented 7 years ago

Currently since scrollMonitor must be instantiated and isn't a singleton it's very difficult to use something like _.debounce to limit the time it takes for the scroll watcher to fire. This is pretty common for people wanting to mess around with scroll events so I think it'd be a good feature to add.

An example of what I'm talking about can be shown in this code pen. http://codepen.io/anon/pen/mAGkyE

stutrek commented 7 years ago

The scrollMonitor is very fast. Your page will jank because of a gigantic body or intense CSS long before it janks because of the scrollMonitor. See the stress test. http://stutrek.github.io/scrollMonitor/demos/stress.html

There is no option for debouncing because it would provide no benefit. No element is entering then exiting the viewport in less time than the debouncing would cover. You can't get every scroll event from the monitor right now, only callbacks when the state of an item changes.

Also note that you are never limiting the time it takes a callback to fire, you're delaying the jank caused by slow code. If you're running into jank issues you should put calls to console.profile('scroll callback') and console.profileEnd('scroll callback') around your code to figure out what's slowing you down.

Nolski commented 7 years ago

It's unfortunate that you seem so set in your ways that you would not even stop to consider a feature request.

I'm not quite sure what you mean when you're saying about page janking. debouncing would be used to limit the speed of scrollMonitor. Perhaps an example would help illustrate the use of this option.

Let's say I want to implement a lazy loader using scrollMonitor. This would be very easy to do using enterViewport on every item that needs to be lazy loaded. However perhaps if the user is scrolling very fast, I don't want to lazy load every item the user scrolls over. Here would be a good time to use debounce to limit the amount of pending network connections going out for the lazy loaded images and only load the images necessary.

stutrek commented 7 years ago

I see. You can use setTimeout (or _.debounce) and the state of the watcher to do this.

var imageWatcher = scrollMonitor.create(img);
imageWatcher.stateChange(_.debounce(function () {
    if (imageWatcher.isInViewport) {
        img.src = 'foo.png';
        imageWatcher.destroy();
    }
}, 300));

Debouncing is a feature that's available in enough other places that I don't think it also needs to be provided here.

stutrek commented 7 years ago

I apologize if I was curt, if you google articles about listening to scroll events almost all of them suggest debouncing or throttling in a very different way than you are. I hope you make the most of the library and thanks for participating.