Scrolling through a shooting event too many times. I just want it to fire at a maximum of, say, once a second

I have an infinite scroll page. It calculates the difference between the end of the page and the current page and loads more content if this difference is small enough. The code is the same as when using jQuery:

$(window).on('scroll', function() { if (window.pageYOffset > loadMoreButton.offsetTop - 1000) # load more content via ajax } 

Now the problem is that every time I scroll, this event fires several times per scroll. I would like to shoot maximum every milliseconds. How should I do it?

+42
javascript
Mar 08 '12 at 6:10
source share
7 answers

Take a look at the throttle method of the Underscore.js library.

http://underscorejs.org/#throttle

The example he gives is exactly what you are asking about - limiting how often you have to handle scroll events.

+37
Mar 08 '12 at 6:13
source share

One way to solve this problem is to determine the time interval and only handle the scroll event once during this time interval. If more than one scroll event occurs during this time period, you ignore it and process it only when this time period has passed.

 var scrollTimer, lastScrollFireTime = 0; $(window).on('scroll', function() { var minScrollTime = 100; var now = new Date().getTime(); function processScroll() { console.log(new Date().getTime().toString()); } if (!scrollTimer) { if (now - lastScrollFireTime > (3 * minScrollTime)) { processScroll(); // fire immediately on first scroll lastScrollFireTime = now; } scrollTimer = setTimeout(function() { scrollTimer = null; lastScrollFireTime = new Date().getTime(); processScroll(); }, minScrollTime); } }); 

This will immediately trigger the first scroll event, and then you will get a scroll event about once every 100ms while the scroll bar moves, and then one last event after the scroll bar stops moving. You can adjust the frequency of the event by changing the argument to setTimeout (currently set to 100).

There is a demo here: http://jsfiddle.net/jfriend00/EBEqZ/ , which you need to open the debug console window, start moving the scroll bar in the content window and then view the time of each scroll event in the debug console window. In my version of Chrome, they are set to a minimum distance of 100 ms, and they seem to occur every 100-200 m.

+31
Mar 08 '12 at 12:15
source share

There is a great explanation from John Resig, the creator of jQuery, to solve this situation.

 var outerPane = $details.find(".details-pane-outer"), didScroll = false; $(window).scroll(function() { didScroll = true; }); setInterval(function() { if ( didScroll ) { didScroll = false; // Check your page position and then // Load in more results } }, 250); 

Source: http://ejohn.org/blog/learning-from-twitter/

+9
Jun 24 '15 at 6:16
source share
 var isWorking = 0; $(window).on('scroll', function() { if(isWorking==0) { isWorking=1; if (window.pageYOffset > loadMoreButton.offsetTop - 1000) # load more content via ajax setTimeout(function(){isWorking=0},1000); } } 
+6
Mar 08 '12 at 6:24
source share
 var now = new Date().getTime(); $(window).scroll( function () { if (window.pageYOffset > loadMoreButton.offsetTop - 1000) { if (new Date().getTime() - now > 1000) { console.log("Task executed once per second"); now = new Date().getTime(); } } }); 

Or

You can use Throttling fonction calls: throttling-function-calls

 function throttle(fn, threshhold, scope) { threshhold || (threshhold = 250); var last, deferTimer; return function () { var context = scope || this; var now = +new Date, args = arguments; if (last && now < last + threshhold) { // hold on to it clearTimeout(deferTimer); deferTimer = setTimeout(function () { last = now; fn.apply(context, args); }, threshhold); } else { last = now; fn.apply(context, args); } }; } 

You can call it like this:

 $('body').on('mousemove', throttle(function (event) { console.log('tick'); }, 1000)); 
+4
Apr 26 '14 at 21:02
source share

Here is a solution that does not require the use of an additional JS library or plugin, the purpose of which is simplicity. It may not be as effective as other implementations, but it is definitely a step forward from triggering the main event every time you scroll.

This was taken from this blog post by Danny Van Couthen. What I used to delay my onscroll() events for my back-to-top button on my blog.

 var timer; $(window).scroll(function() { if(timer) { window.clearTimeout(timer); } timer = window.setTimeout(function() { // actual code here. Your call back function. console.log( "Firing!" ); }, 100); }); 

You can also improve performance by displacing variables from the callback function to avoid unnecessary recounts, for example, the value of $(window).height() or the height of some static div element that does not change after the page loads.

Here is an example that is adapted from my use case.

 var scrollHeight = $("#main-element").height(); //never changes, no need to recalculate. $(window).on('scroll', function() { if (timer) window.clearTimeout(timer); timer = window.setTimeout(function() { var scrollPosition = $(window).height() + $(window).scrollTop(); if ($(window).scrollTop() < 500) $(".toggle").fadeIn(800); else $(".toggle").fadeOut(800); }, 150); //only fire every 150 ms. }); 

This limits the actual function to only be executed every 150 ms, otherwise the reset timer returns to 0 if 150 ms has not passed. Adjust the value according to what you need.

+3
Jun 24 '15 at 6:08
source share

the multiple scroll arrow is correct, and you can get the scroll position differently each time. I think you need to set a timer when you first get into the scroll event, as you mentioned x milliseconds, and also write down the timestamp, and then next time start scrolling the event, check the last run time and ignore it if it is within x milliseconds, and do real work in your action with a timer.

0
Mar 08 '12 at 6:16
source share



All Articles