zoukankan      html  css  js  c++  java
  • 防抖和节流

    防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。 在实时检查输入时,如果我们绑定onkeyup事件发请求去服务端检查,用户输入过程中,事件的触发频率也会很高,会导致大量的请求发出,响应速度会大大跟不上触发。

    针对此类快速连续触发和不可控的高频触发问题,debounce 和 throttling 给出了两种解决策略;

    debounce,去抖动。策略是当事件被触发时,设定一个周期延迟执行动作,若期间又被触发,则重新设定周期,直到周期结束,执行动作。 这是debounce的基本思想,在后期又扩展了前缘debounce,即执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定。

    延迟debounce,示意图:

    前缘debounce, 示意图

    debounce的特点是当事件快速连续不断触发时,动作只会执行一次。 延迟debounce,是在周期结束时执行,前缘debounce,是在周期开始时执行。但当触发有间断,且间断大于我们设定的时间间隔时,动作就会有多次执行。

    debounce 的实现

    周期内有新事件触发时,重置定时器开始时间撮,定时器执行时,判断开始时间撮,若开始时间撮被推后,重新设定延时定时器,是否立即执行选项

    // 增加前缘触发功能
    var debounce = (fn, wait, immediate=false) => {
    let timer, startTimeStamp=0;
    let context, args;

    let run = (timerInterval)=>{
    timer= setTimeout(()=>{
    let now = (new Date()).getTime();
    let interval=now-startTimeStamp
    if(interval<timerInterval){ // the timer start time has been reset,so the interval is less than timerInterval
    console.log('debounce reset',timerInterval-interval);
    startTimeStamp=now;
    run(timerInterval-interval); // reset timer for left time
    }else{
    if(!immediate){
    fn.apply(context,args);
    }
    clearTimeout(timer);
    timer=null;
    }

    },timerInterval);
    }

    return function(){
    context=this;
    args=arguments;
    let now = (new Date()).getTime();
    startTimeStamp=now; // set timer start time

    if(!timer){
    console.log('debounce set',wait);
    if(immediate) {
    fn.apply(context,args);
    }
    run(wait); // last timer alreay executed, set a new timer
    }

    }

    }

    throttling,节流的策略是,固定周期内,只执行一次动作,若有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期。 节流策略也分前缘和延迟两种。与debounce类似,延迟是指 周期结束后执行动作,前缘是指执行动作后再开始周期。

    延迟throttling示意图:

    前缘throttling 示意图:

    简单版: 定时器期间,只执行最后一次操作
    var throttling = (fn, wait) => {
    let timer;
    let context, args;

    let run = () => {
    timer=setTimeout(()=>{
    fn.apply(context,args);
    clearTimeout(timer);
    timer=null;
    },wait);
    }

    return function () {
    context=this;
    args=arguments;
    if(!timer){
    console.log("throttle, set");
    run();
    }else{
    console.log("throttle, ignore");
    }
    }

    }

    原文:https://blog.csdn.net/hupian1989/article/details/80920324

  • 相关阅读:
    在日本被禁止的コンプガチャ設計
    Starling常见问题解决办法
    Flixel引擎学习笔记
    SQLSERVER中修复状态为Suspect的数据库
    T4 (Text Template Transformation Toolkit)实现简单实体代码生成
    创建Linking Server in SQL SERVER 2008
    Linq to Sql 与Linq to Entities 生成的SQL Script与分页实现
    Linq to Entity 的T4 模板生成代码
    在VisualStudio2008 SP1中调试.net framework 源代码
    使用HttpModules实现Asp.net离线应用程序
  • 原文地址:https://www.cnblogs.com/caozhuzi/p/11175735.html
Copyright © 2011-2022 走看看