首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

函数防抖:让你的函数休息一下

函数防抖,是指防止函数在极短的时间内反复调用,造成资源的浪费

考虑一下电梯关门的场景,现代的大部分电梯都可以通过红外,感知到是否有人进入,为了避免夹到人,同时为了等待后面的人,电梯关门的时间往往有这么一种规则:始终保证电梯门在最后一个人进入后3秒后关闭。如果有人进入后,还没有等到3秒又有人进来了,电梯门会以最后一次进入的时间为计时起点,重新等待3秒。

再考虑一个页面上的场景,页面上的某些事件触发频率非常高,比如滚动条滚动、窗口尺寸变化、鼠标移动等,如果我们需要注册这类事件,不得不考虑效率问题,又特别是事件处理中涉及到了大量的操作,比如:

当窗口尺寸发生变化时,哪怕只变化了一点点,都有可能造成成百上千次对处理函数的调用,这对网页性能的影响是极其巨大的。于是,我们可以考虑,每次窗口尺寸变化、滚动条滚动、鼠标移动时,不要立即执行相关操作,而是等一段时间,以窗口尺寸停止变化、滚动条不再滚动、鼠标不再移动为计时起点,一段时间后再去执行操作,就像电梯关门那样。

再考虑一个搜索的场景(例如百度),当我在一个文本框中输入文字(键盘按下事件)时,需要将文字发送到服务器,并从服务器得到搜索结果,这样的话,用户直接输入搜索文字就可以了,不用再去点搜索按钮,可以提升用户体验,类似于下面的效果:

上面的效果,我没有点击搜索按钮,也没有按回车键,只是写了一些搜索的文字而已。

可是如何来实现上面的场景呢?如果文本框的文字每次被改变(键盘按下事件),我都要把数据发送到服务器,得到搜索结果,这是非常恐怖的!想想看,我搜索“google”这样的单词,至少需要按6次按键,就这一个词,我需要向服务器请求6次,并让服务器去搜索6次,但我只需要最后一次的结果就可以了。如果考虑用户按错的情况,发送请求的次数更加恐怖。这样就造成了大量的带宽被占用,浪费了很多资源。

如何避免这样的问题呢?你再仔细看看百度的处理方式:

你会发现,真正的搜索行为,并不是每次按键都会触发的,只有当用户停止按键一段事件后才会触发。

于是,为了满足这种类型场景,我们可以开发一个通用的函数,这个函数要满足以下功能:

调用该函数后,不立即做事,而是一段时间后去做事

如果在等待时间内调用了该函数,重新计时

这样的功能,就叫做函数防抖,其实就是防止函数短时间内被调用多次。要完成该函数,需要给予两个条件:

告诉我一段时间后要做什么事(这里应该是一个回调函数,即函数作为参数)

告诉我要等待多长时间(毫秒)

基于这样的理解,我们可以编写如下的代码:

现在来测试一下这个函数:

效果如下:

虽然我们实现了效果,可是仔细想想,目前这个防抖函数还是太年轻,太简单,有时候还很幼稚。

因为它使用了一个全局变量,这意味着,页面上所有需要防抖的地方都要共用这个变量,如果我同时要对窗口尺寸改变事件和文本框按键事件进行防抖,就办不到了。

于是,我决定把这个变量写到函数里面去:

但是这样子还是有问题,这样的话,每次调用防抖函数都会得到一个新的计时器,过去的计时器找不到了。

为了解决这个问题,我决定把代码改造成以下结构:

这样一来,函数仅仅负责生成一个,保证每次调用都会有一个新的产生即可,将防抖的工作,交给了返回的函数去完成。今后如果我要对某一个操作进行防抖,我只需要调用函数来得到一个操作函数,后面反复去调用操作函数即可。

下面是测试的代码:

下面是执行效果:

目前,我们的防抖函数还无法传递参数给回调函数,只要稍稍做一点改变,即可实现参数的传递:

之后,我们就可以在调用时传递参数了:

有了防抖函数,我们将来遇到鼠标移动、窗口尺寸改变等需要大量调用同一个函数的时候,就可以使用它来降低执行频率,保证执行效率。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181223G14LIK00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券