-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
underscore 函数节流的实现 #22
Comments
问个问题,remaing > wait 这种情况好像不可能发生吧 |
有注释
|
@hanzichi 不好意思,眼拙了- - |
timeout = null设置为null,不仅仅是为了防止内存泄漏,而是clearTimeout(timeout)后,timeout的值并不会清空,如果不设置为null,就不能根据!timeout设置下次的timeout |
大神,想问下这里:
|
@ginnko |
@ginnko 2去掉之后remaining就一直等于wait,if 语句还怎么执行 |
@anotherleon |
Throttle
上文 我们聊了聊函数去抖(debounce),去抖的作用简单说是 使连续的函数执行降低到一次(通常情况下此函数为 DOM 事件的回调函数),核心实现也非常简单,重复添加定时器即可(具体可以参考 上文)。本文我们聊聊函数节流(throttle)。
简单的说,函数节流能使得连续的函数执行,变为 固定时间段 间断地执行。
还是以 scroll 事件为例,如果不加以节流控制:
轻轻滚动下窗口,控制台打印了 N 多个 hello world 字符串。如果 scroll 回调不是简单的打印字符串,而是涉及一些 DOM 操作,这样频繁的调用,低版本浏览器可能就会直接假死,我们希望回调可以间隔时间段触发,比如上面的例子每 1000ms 打印一次,如何实现之?
大概有两种方式(underscore 也并用了这两种方式)。其一是用时间戳来判断是否已到回调该执行时间,记录上次执行的时间戳,然后每次触发 scroll 事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经到达 1000ms,如果是,则执行,并更新上次执行的时间戳,如此循环;第二种方法是使用定时器,比如当 scroll 事件刚触发时,打印一个 hello world,然后设置个 1000ms 的定时器,此后每次触发 scroll 事件触发回调,如果已经存在定时器,则回调不执行方法,直到定时器触发,handler 被清除,然后重新设置定时器。
underscore 实现
如果是一般的使用场景,则上面的两个方式大同小异,都可以应用,但是 underscore 考虑了高级配置,即可以选择是否需要响应事件刚开始的那次回调(配置 leading 参数),以及事件结束后的那次回调(配置 trailing 参数)。 还是以 scroll 举例,设置 1000ms 触发一次,并且不配置 leading 和 trailing 参数,那么 scroll 开始的时候会响应回调,scroll 停止后还会触发一次回调。如果配置 {leading: false},那么 scroll 开始的那次回调会被忽略,如果配置 {trailing: false},那么 scroll 结束的后的那次回调会被忽略。需要特别注意的是,两者不能同时配置!
所以说,underscore 的函数节流有三种调用方式,默认的(有头有尾),设置 {leading: false} 的,以及设置 {trailing: false} 的。再来看上面说的 throttle 的两种实现,第一种方式有缺陷,当事件停止触发时,便不能响应回调,所以如果没有设置 {trailing: false} (需要执行最后一次方法)也不能执行最后一次方法,这时我们需要用到定时器;而单纯的定时器方式,也有漏洞,因为使用了定时器延迟执行,所以当事件触发结束时还存在定时器,{trailing: false} 设置无法生效(还会执行最后一次方法)。所以我们需要两者并用。
上 underscore 源码,包含大量注释:
调用也是非常的简单:
有兴趣的可以琢磨下它是如何实现两种方式并用的,可以将我代码块中的三处注释打开看下(分别打印了 A,B 以及 remaining )。
Read more
The text was updated successfully, but these errors were encountered: