window scroll 事件处理之 “throttle” 和 “debounce”

#window对象scroll事件处理之 throttle 和 debounce 概念请点这里

现状描述

天猫几乎所有的频道都有 下拉刷新 的逻辑。其中,品牌特卖和焕新在做下拉刷新的时候均使用了一个叫做 bottomloader 的组件。该组件中采用了 throttle 方法对于连续的scroll事件所触发业务逻辑(包含数据加载)的次数进行了稀释,从原生的像素级别的滑动触发,稀释到了间隔几百毫秒触发一次,从而极大的降低了scroll事件对业务逻辑的高频触发,提高了滑动流畅度以及页面性能。

代码如下:

var detect = throttle(function(){
	//添加业务逻辑
}, 200);

window.addEventListener('scroll', detect, false);

function throttle(action, delay){
	 var self = this;
	 var curr = +new Date();
	 if (curr - self.last > delay){
	   action.apply(this, arguments);
	   self.last = curr ;
	 }
}

## 问题发现 这两个频道的测试同学做回归的时候均曾提出,当屏幕被快速滑动到底部时候,下一个Page的资源会经常加载不出来。特别是在 Chrome 模拟器中,通过鼠标拖动可以达到极快的滑动速度时,资源加载不出的情况更是发生频率很高。经排查,原因也很简单,就是由于代码中采用 throttle 方法做了节流。当使用者滑动超快,一次滑动事件的时间低于设定的节流阈值( 比如 500 毫秒),滑动事件就无法触发具体的业务逻辑,无法加载新数据。

调整方式

目前的修改办法是简单的将阈值改小,降至 100 毫秒,将数据加载不出的可能性降低。但是并不能根本的解决这个问题。因为极端情况下,100 毫秒以内的scroll事件也可以产生。同时,页面性能也会因为阈值小、scroll事件触发业务逻辑频率升高造成页面性能下降。

根本解决

个人倾向于采用 debounce 的方式,为每一个scroll事件触发的业务逻辑设定一个执行的 timeout,并将所有与前一个scroll事件间隔小于该阈值(即 timeout)的scroll事件触发的业务逻辑都进行丢弃,直到上一个事件完成后经过的时间已经超过该阈值。

代码如下:

var timer = null;
window.addEventListener('scroll', function () {
      if (typeof timer === 'number') {
          clearTimeout(timer);
      }
      timer = setTimeout(function () {
          //添加业务逻辑
      },200);
}, false);

如此则有:

  1. 无论用户/测试人员以多快速度滑动页面,一旦到页面底部,滑动事件均会由于页面无新内容而被迫停止。此时,采用了debounce 方式,scroll事件触发的业务逻辑确保能被执行;
  2. 丢弃与前一个scroll事件间隔小于特定阈值的后一个事件的业务逻辑,即就是对scroll事件触发业务逻辑次数进行了稀释,也同样提高了页面效率。
时间: 2024-09-10 23:45:50

window scroll 事件处理之 “throttle” 和 “debounce”的相关文章

javascript中的throttle和debounce浅析_基础知识

throttle 我们这里说的throttle就是函数节流的意思.再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制.主要应用的场景比如: 1.鼠标移动,mousemove 事件2.DOM 元素动态定位,window对象的resize和scroll 事件 有人形象的把上面说的事件形象的比喻成机关枪的扫射,throttle就是机关枪的扳机,你不放扳机,它就一直扫射.我们开发时用的上面这些事件也是一样,你不松开鼠标,它的事件就一直触发.例如: 复制代码 代码如下: var resizeT

JavaScript中定时控制Throttle、Debounce和Immediate详解_javascript技巧

前言 我们称这些行为events(事件),和响应callbacks(回调).连续的事件流被称为event stream(事件流).这些行为发生的速度不是我们能手动控制的.但是我们可以控制何时和如何激活正确的响应.有一些技术为我们提供精确的控制. Throttle 在现代浏览器中,帧速率为60fps是流畅性能的目标,给定我们16.7ms的时间预算用于响应一些事件所有需要的更新.这样可以推断,如果每秒发生n个事件并且回调执行,需要t秒的时间,为了流畅运行, 1 / n >= t 如果t以毫秒为单位,

javascript- 窗口每滑动一次,为什么$(window).scroll()运行的次数不止1次?

问题描述 窗口每滑动一次,为什么$(window).scroll()运行的次数不止1次? 窗口每滑动一次,为什么$(window).scroll()运行的次数不是1?但是如果使用$(""div"").scroll()却只调用一次. 你看W3school上的例子,$(""div"").scroll()确实只调用了一次.但是你改成$(window).scroll(),即查看窗口的滑动时,能发现调用了不只一次 解决方案 楼主用的IE

jQuery/JS 的 window.scroll 在 FireFox 不正常

问题描述 jQuery/JS 的 window.scroll 在 FireFox 不正常 请问以下这段 jQuery 的 window onscroll 代码, 在 IE.Chrome 正常,滑鼠卷一次,才会 alert 一次. 但在 FireFox 疯狂,滑鼠卷一次,就会 alert 非常多次. 请问此 window onscroll 和 FireFox 不和的问题,要怎么解决? 我是希望 FireFox 能和 IE.Chrome 一样,能够滑鼠卷一次,只要 alert 一次就好. (若网友愿

Javascript Throttle & Debounce应用介绍_基础知识

Throttle 无视一定时间内所有的调用,适合在发生频度比较高的,处理比较重的时候使用. 复制代码 代码如下: var throttle = function (func, threshold, alt) { var last = Date.now(); threshold = threshold || 100; return function () { var now = Date.now(); if (now - last < threshold) { if (alt) { alt.app

window的事件处理

问题描述 问题描述:一个界面上,有个大的PictureBox,里面是一排紧邻的小PictureBox控件,如何实现按下鼠标,拖动鼠标时,把经过的小PictureBox都选中????补充:我尝试在每个小picturebox里都添加mouseDown,up,move事件,发现sender都是按下时的那个控件,而且move里e的坐标是相对按下鼠标时那个控件的坐标而言的.根据这些信息,应该也可以实现上面描述的功能.我想问问有没有更好的方法.希望能回答时能说清楚点,小白谢过. 解决方案 解决方案二:自己绘

JS魔法堂:函数节流(throttle)与函数去抖(debounce)

一.前言   以下场景往往由于事件频繁被触发,因而频繁执行DOM操作.资源加载等重行为,导致UI停顿甚至浏览器崩溃.   1. window对象的resize.scroll事件   2. 拖拽时的mousemove事件   3. 射击游戏中的mousedown.keydown事件   4. 文字输入.自动完成的keyup事件   实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理:而其他事件大多的需求是以一定的频率执行后续处理.针对这两种需求就出现了debo

JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)_javascript技巧

函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用. 函数节流的原理挺简单的,估计大家都想到了,那就是定时器.当我触发一个时间时,先setTimout让这个事件延迟一会再执行,如果在这个时间间隔内又触发了事件,那我们就clear掉原来的定时器,再setTimeout一个新的定时器延迟一会执行,就这样. 以下场景往往由于事件频繁被触发,因而频繁执行DOM操作.资源加载等重行为,导致UI停顿甚至浏览器崩溃. 1.

JavaScript Window浏览器对象模型方法与属性汇总

  本文给大家汇总分享的是JavaScript Window浏览器对象模型方法与属性,十分的细致全面,这里推荐给大家,有需要的小伙伴可以参考下. Window 对象 所有浏览器都支持 window 对象.它表示浏览器窗口. 所有 JavaScript 全局对象.函数以及变量均自动成为 window 对象的成员. 全局变量是 window 对象的属性. 全局函数是 window 对象的方法. 1. open方法 语法格式: window.open(URL,窗口名称,窗口风格) 功能:打开一个新的窗