• 防抖(debounce)和节流(throttle)


    背景:
            我们在日常开发中,经常会遇到处理系统高频回调的问题,比如:scrollView 快速滚动的回调(scrollViewDidScroll),又比如用户输入文本时textView的回调(textViewDidChange),在这些场景下,为了降低CPU负担,我们一般会使用一些方法降低高频次计算,这篇文章介绍解决高频次计算的两种方法:防抖(debounce) 和 节流(throttle)。 

    防抖

    首先提出第一种思路,防抖:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:

    如果在200ms内,事件再次触发,当前的计时取消,重新开始计时

    如果在200ms内,事件没有触发,那么执行事件的处理函数 

    总结:指定时间内连续触发事件,只在最后一次事件触发结束后的指定时间之后,执行一次处理函数。

    1. /**
    2. * 函数防抖
    3. * @param fn 函数
    4. * @param delay 延迟执行毫秒数
    5. * @param immediate true 表立即执行,false 表非立即执行
    6. */
    7. export function _debounce(fn,delay,immediate){
    8. var delay = delay||200;
    9. var timer;
    10. return function(){
    11. var th = this;
    12. var args = arguments;
    13. if (timer) {
    14. clearTimeout(timer);
    15. }
    16. if(immediate){
    17. var callNow = !timer
    18. timer = setTimeout(()=>{
    19. timer = null;
    20. },delay)
    21. if (callNow) fn.apply(th, args)
    22. }else {
    23. timer = setTimeout(function(){
    24. timer = null;
    25. fn.apply(th,args);
    26. },delay)
    27. }
    28. }
    29. }

    节流

    当事件第一次触发的时候,也是不立即执行函数,而是给出一个期限值比如200ms,开始计时,然后

    在200ms内,再次触发的事件被全部忽略,计时结束后,执行一次函数,并且清理计时器。

    200ms结束后,重新开始上述循环 

    总结:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。

    1. //节流
    2. // 函数节流
    3. // param fn 函数
    4. // param interval 延迟执行毫秒数
    5. // param type 1 表时间戳版,2 表定时器版
    6. //时间戳和定时器区别:时间戳版本的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候
    7. export function _throttle(fn,interval,type) {
    8. if(type === 1){
    9. let previous = 0;
    10. }else if(type === 2){
    11. let timeout;
    12. }
    13. var interval = interval || 200;
    14. return function () {
    15. var th = this;
    16. var args = arguments;
    17. if(type === 1){
    18. let now = Date.now();
    19. if (now - previous > interval){
    20. fn.apply(th,args);
    21. previous = now;
    22. }
    23. }else if(type === 2){
    24. if(!timeout){
    25. timeout = setTimeout(()=> {
    26. timeout = null;
    27. fn.apply(th,args)
    28. }, interval);
    29. }
    30. }
    31. }
    32. }

    总结:从降低CPU计算频次来说,肯定是 debounce 效果更好,因为它在整个高频回调期间,只会触发一次。

    但 debounce 计算频次少,带来的影响就是可能会损失用户的体验。比如如果在 scrollViewDidScroll 中使用了 debounce 来触发某些渲染逻辑,那么用户如果一直在滚动屏幕,只有在用户松手后,才能把屏幕渲染出来,整个滚动过程是无法加载的。

    考虑到现在CPU计算能力越来越强,在解决高频回调问题面前,我们可以优先选择 throttle 的方案 。

  • 相关阅读:
    一个使用typescript实现的excel转json的工具
    linux 编译 llvm + clang
    Cilium系列-16-CiliumNetworkPolicy 实战演练
    Kubesphere之部署MySQL
    【云原生监控系列第二篇】Prometheus进阶——PromQL数据类型
    leetcode做题笔记173. 二叉搜索树迭代器
    ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
    使用JSAPl来做一个倒计时的效果
    大模型从入门到应用——LangChain:代理(Agents)-[代理执行器(Agent Executor):处理解析错误、访问中间步骤和限制最大迭代次数]
    es6---如何在项目中和平时练习中应用es6语法
  • 原文地址:https://blog.csdn.net/qq_24892029/article/details/125623701