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

    1,节流

      节流就是对连续的函数触发,在设定的间隔时间段内,只让其执行一次。

      先来看看js高级程序设计3里面节流的代码

    function throttle (method, context, wait) {
        clearTimeout(method.tId)
         method.tId = setTimeout(function () {
             method.call(context)
         }, wait)
    }

           当函数连续执行的时候,如果之前的定时器还没执行,就把它清除了,再从新设置一个新的定时器。

      我们可以对这个进行改进

    function throttle (fn, wait) {
    let timeout;
    let prevTime = 0;
    return function(...args) { //返回一个函数
    let now = new Date();
    let remaining = wait - (now - prevTime) // 下一次执行的时间,
    if (remaining <=0 || remaining > wait) { // 如果下一次的时间小于等于0,立刻执行一次函数,并把时间戳改为当前的时间。
    clearTimeout(timeout)
    timeout = null
    prevTime = now
    fn.apply(this, args)
    } else if (!timeout) { // 如果当前没有定时器 那么就新加一个定时器。
    timeout = setTimeout(() => {
    timeout = null;
    prevTime = new Date();
    fn.apply(this, args)
    }, remaining)
    }
    }
    }

      第一次执行: timeout为undefined, prevTime为0     remaining为负数,走if的第一个,立即执行了函数并将下次时间改成当前时间

      第二次执行: 下一次时间为正,定时器还是为undefined,走if的第二个,设置定时器

         下一次执行(不超过wait时间内) :  remaining大于0,定时器为true,所以直接跳出

      

        understore里面的节流考虑了两个高级的配置:  是否在第一次触发的时候就执行函数 和  最后一次的定时器触发的执行函数。还提供了节流的取消函数。

    function throttle(fn, wait, option = {}) {
            let timeout;
            let prevTime = 0
            let throttled = function(...args){
                let now = new Date();
                if (!prevTime && option.leading === false) prevTime = now;
                let remaining = wait - (now - prevTime);
                if (remaining <= 0 || remaining > wait) {
                    if (timeout) {
                        clearTimeout(timeout)
                        timeout = null;
                    }
                    prevTime = now
                    fn.apply(this, args)
                } else if (!timeout && option.trailing !== false) {
                    timeout = setTimeout(() => {
                        prevTime = option.leading === false ? 0 : new Date;
                        fn.apply(this, args)
                    })
                }
            }
            throttled.cancel = () => {
                clearTimeout(timeout);
                prevTime = 0;
                timeout = null;
            }
            return throttled
    }

      除了加了两个配置项和取消函数,别的基本都是一样的。

      需要注意的是,首次不执行和最后不执行这两个不能同时配置,只能配置一个。

    2,防抖

      其实我感觉防抖和节流差别不大,主要的差别在于: 在wait的时间内,反复触发函数的话,节流不会理会这些,而防抖的话,只要你触发了,他就会清除之前的定时器,从新设置一个定时器。

      比如说坐电梯,如果是节流的话,电梯等待时间为5S,从第一个人进电梯开始算,到5S后他就会关门运行。

               如果是防抖的话,电梯等待时间为5S,在这5S之内,如果有人进电梯,他就会重新计时,只有在5S中没有人进电梯了,电梯才关门运行。

    function debounce (fn, wait) {
    let timeout;
    return function(...args) {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => {
    fn.apply(this, args)
    }, wait)
    }
    }

      返回一个函数, 先清除之前的定时器,然后再新加定时器。

      underscore里面的防抖添加了一个高级配置,是否立即执行一次函数。

    function debounce(fn, wait, immediate) {
           let timeout;
           return function(...args) {
               let callNow = immediate && !timeout;
               if (timeout) clearTimeout(timeout);
               timeout = setTimeout(() => {
                   timeout = null;
                   if (!immediate) fn.apply(this, args)
               }, wait)
               if (callNow) fn.apply(this, args)
           }
    }

      这里添加了immediate这个配置项,如果为true的话,那么触发第一次的时候就执行了要执行的函数,定时器里面不执行。

      

      

  • 相关阅读:
    JavaScript 语句
    JavaScript语法
    JavaScript输出
    JavaScript用法
    JavaScript简介
    利用IDEA构建springboot应用-构建好SpringBoot + SSM 框架
    SP2010开发和VS2010专家"食谱"--第二章节--工作流(4)--创建自定义任务表单
    SP2010开发和VS2010专家"食谱"--第二章节--工作流(3)--创建工作流里的任务
    SP2010开发和VS2010专家"食谱"--第二章节--工作流(2)--部署工作流的InfoPath表单
    SP2010开发和VS2010专家"食谱"--第二章节--工作流(1)--创建带有初始表单的网站工作流
  • 原文地址:https://www.cnblogs.com/wjyz/p/10225193.html
Copyright © 2011-2022 走看看