使用rxjs以及javascript解决前端的防抖和节流,以及防抖在vue中的用法

8 篇文章 0 订阅

JavaScript实现方式:

防抖

触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;
思路:每次触发事件时都取消之前的延时调用方法:

举个例子:做一个自动查询的功能
假装下面的代码是从服务器获取的数据(下面会用到):

// 假装这是个接口
function getData(val){
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(!val){resolve([]);return;}
            var json = [
                {name:"萧山国际机场",jianpin:"xsgjjc",threeCode:"xjc"},
                {name:"北京南苑机场",jianpin:"bjnyjc",threeCode:"byc"},
                {name:"上海虹桥机场",jianpin:"shhqjc",threeCode:"hcg"},
                {name:"成都机场",jianpin:"cdjc",threeCode:"cjc"}
            ];
            var newJson = json.filter(function(item){
                return item.name.indexOf(val)==0||item.jianpin.indexOf(val)==0||item.threeCode.indexOf(val)==0
            });
            resolve(newJson);
        },1000)
    })
}

 在文本框输入关键字去服务器实时请求对应的数据,如下代码;

<body>
    <input type="text" placeholder="简拼/汉字/三字码" id="test"/>
    <script>
        var $test = document.getElementById('test');
        $test.onkeyup =autoSearch;
        function autoSearch(){
            var val = $test.value;
            getData(val).then(function(res){console.log(res)})
        }   
    </script>
</body>

结果如下图,在运行的时候会发现存在一个问题:这个函数的默认执行频率太高了,高到什么程度呢?我们输入"萧山",函数执行了9次!,然而我们需要的只是最后一次.

然而实际上我们并不需要如此高频的反馈,毕竟浏览器和服务器的性能是有限的,所以接着讨论如何优化这种场景。


function debounce(fn,delay){
    let timer = null
    //闭包
    return function() {
        if(timer){
            clearTimeout(timer) 
        }
        timer = setTimeout(fn,delay)
    }
}

// 改写上面的代码
...
 $test.onkeyup = debounce(autoSearch,1000);
...

再次运行结果就是我们想要的结果了:

节流

高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。
思路:每次触发事件时都判断当前是否有等待执行的延时函数。

还是上面的例子:如果某个用户闲的蛋疼,一直按着键盘不撒手,那么只要她在1秒内重新按了键盘,就永远不会有结果输出,但是我们还想要在某个时间间隔之后给出反馈呢

使用方法跟debounce一样。代码逻辑也类似。在触发时超过间隔时间interval ms则执行。否则不执行。if判断中的setTimeout是保证最后一次事件触发后能够调用,所以每次执行没到间隔时间时先清除timer,再重新启动timer。而在达到间隔时间时执行函数。代码逻辑也很简单,不用多说,相信聪明的你一看就能明白。

function throttle(fn,timeout){
   var timer = null;
    return function (){
        if(timer) {
            return;
        }
        timer = setTimeout(() => {
            fn.apply(this,arguments); // 修正this为当前的输入框,调用的时候不可以使用箭头函数
            timer = null
        }, timeout);
    }
}

// 改写上面的代码
...
 $test.onkeyup = throttle(autoSearch,1000);
...

运行结果就是我们想要的结果了(不管文本框输入什么内容,没1秒输出一次结果):

rxjs实现方式

使用rxjs,使用起来更方便(要记得要安装或者引入rxjs哦)
使用debounceTime(防抖)和throttleTime(节流)操作符,对流进行限制,然后再订阅符合规则的流,输出想要的数据即可,
rxjs的可以参考官方文档.RxJS 中文文档
也可以查看Rx观测的交互图:
debounceTime: RxMarbles: Interactive diagrams of Rx Observables
throttleTime:RxMarbles: Interactive diagrams of Rx Observables
关于操作符:rxjs操作符整合_榴莲不好吃的博客-CSDN博客
例子:

<head>
    <script src="https://cdn.bootcss.com/rxjs/6.0.0-alpha.3/Rx.min.js"></script>
</head>

<body>
防抖:<input type="text" placeholder="简拼/汉字/三字码" id="debounce"/><br/><br/>
节流:<input type="text" placeholder="简拼/汉字/三字码" id="throttle"/>
<script>
    var $debounce = document.getElementById('debounce');
    var $throttle = document.getElementById('throttle');
    const debounce$ = Rx.Observable.fromEvent($debounce, 'input');
    const throttle$ = Rx.Observable.fromEvent($throttle, 'input');
    // 节流
    debounce$
        .debounceTime(1000)
        .subscribe(function (e) {
            var value = e.target.value;
            console.log('防抖:'+value)
        });
    // 防抖
    throttle$
        .throttleTime(1000)
        .subscribe(function (e) {
            var value = e.target.value;
            console.log('节流:'+value)
        });
</script>
</body>

结果:


 


 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值