Step-By-Step icon indicating copy to clipboard operation
Step-By-Step copied to clipboard

节流(throttle)函数的作用是什么?有哪些应用场景,请实现一个节流函数。

Open YvetteLau opened this issue 6 years ago • 45 comments

上周五刚复习过防抖,趁热打铁,巩固一下节流~

YvetteLau avatar May 27 '19 00:05 YvetteLau

函数节流: 指定时间间隔内只会执行一次任务;

以判断页面是否滚动到底部为例,普通的做法就是监听 window 对象的 scroll 事件,然后再函数体中写入判断是否滚动到底部的逻辑:

$(window).on('scroll', function() {
  // 判断是否滚动到底部的逻辑
  let pageHeight = $('body').height(),
    scrollTop = $(window).scrollTop(),
    winHeight = $(window).height(),
    thresold = pageHeight - scrollTop - winHeight;
  if (thresold > -100 && thresold <= 20) {
    console.log('end');
  }
});

no-throttle

这样做的一个缺点就是比较消耗性能,因为当在滚动的时候,浏览器会无时不刻地在计算判断是否滚动到底部的逻辑,而在实际的场景中是不需要这么做的,在实际场景中可能是这样的:在滚动过程中,每隔一段时间在去计算这个判断逻辑。而函数节流所做的工作就是每隔一段时间去执行一次原本需要无时不刻地在执行的函数,所以在滚动事件中引入函数的节流是一个非常好的实践:

// 添加节流函数
function throttle(fn, interval = 300) {
  let canRun = true;
  return function() {
    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      fn.apply(this, arguments);
      canRun = true;
    }, interval);
  };
}
$(window).on(
  'scroll',
  throttle(function() {
    // 判断是否滚动到底部的逻辑
    let pageHeight = $('body').height(),
      scrollTop = $(window).scrollTop(),
      winHeight = $(window).height(),
      thresold = pageHeight - scrollTop - winHeight;
    if (thresold > -100 && thresold <= 20) {
      console.log('end');
    }
  })
);

throttle 加上函数节流之后,当页面再滚动的时候,每隔 300ms 才会去执行一次判断逻辑。 简单来说,函数的节流就是通过闭包保存一个标记(canRun = true),在函数的开头判断这个标记是否为 true,如果为 true 的话就继续执行函数,否则则 return 掉,判断完标记后立即把这个标记设为 false,然后把外部传入的函数的执行包在一个 setTimeout 中,最后在 setTimeout执行完毕后再把标记设置为 true(这里很关键),表示可以执行下一次的循环了。当 setTimeout 还未执行的时候,canRun 这个标记始终为 false,在开头的判断中被 return 掉。

防抖和节流都是为了避免事件的频繁触发,有些事件无论是防抖还是节流都做到性能上的优化,要根据业务需求选择合适的方案。

JavaScript函数节流与函数防抖

今日打卡完毕,首次沙发 嘻嘻嘻

lqzo avatar May 27 '19 02:05 lqzo

函数节流: 指定时间间隔内只会执行一次任务; 场景的运用 => 滚动条滚动到底部 function throttle(fn, interval) { let flag= true; return function() { if (!flag) return; flag= false; setTimeout(() => { fn.apply(this, arguments); flag= true; }, interval); }; }

shenanheng avatar May 27 '19 02:05 shenanheng

函数节流,是指如果一个事件不停地触发,那么就每隔一定的时间才执行回调函数,回调函数的执行会被稀释。

应用场景: 函数节流典型的应用场景就是图片懒加载,用户下啦页面,需要监听wheel事件,然后判断是否应该展示图片。这个判断就可以用函数节流来做,没必要一直判断。

实现:

  • 时间戳方式
function throttle(fn, delay) {
    let pre = 0;
    return function() {
        let now = Date.now();
        if ((now - pre) >= delay) {
            fn.apply(this, arguments);
            pre = now;
        }
    }
}
  • 定时器版
function throttle(fn, delay) {
    return function() {
        if (!throttle.timer) {
            fn.apply(this, arguments);
        }
        throttle.timer = setTimeout(function() {
            throttle.timer = true;
        }, delay);
    }
}

AILINGANGEL avatar May 27 '19 02:05 AILINGANGEL

函数节流以及其使用场景

节流: 节流就是流体在管道内流动,突然遇到截面变窄,而使压力下降的现象。节制流入或流出,尤指用节流阀调节。

出处:语出《荀子·富国》:“百姓时和、事业得叙者,货之源也; 等赋府库者,货之流也。故明主必谨养其和,节其流,开其源,而时斟酌焉,潢然使天下必有馀而上不忧不足。”后以“开源节流”指开辟财源,节约开支。

其实作用跟定义就是上面的意思,在日常开发中,我们经常会有频繁调用或执行某一函数的需求,其实按实际用户情况,可能 100ms 甚至 1s 调用一次就OK,所以需要用到函数节流,在一定的时间间隔之后再执行函数。

场景很多,常见的有:

  1. 屏幕尺寸变化时页面内容的变动,执行相应逻辑;

  2. 监听鼠标滚动时间,执行相应逻辑;

  3. 监听重复点击时的时间,执行相应逻辑

下面依然是 lodash 的代码实现:

function isObject(value) {
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}

function throttle(func, wait, options) {
  let leading = true
  let trailing = true

  if (typeof func !== 'function') {
    throw new TypeError('Expected a function')
  }
  if (isObject(options)) {
    leading = 'leading' in options ? !!options.leading : leading
    trailing = 'trailing' in options ? !!options.trailing : trailing
  }
  return debounce(func, wait, {
    leading,
    trailing,
    'maxWait': wait,
  })
}

使用方法如下:

var 打印一些东西啦 = function (event) {
	console.log(event);
};

document.querySelector('html').addEventListener('click', throttle(打印一些东西啦, 1000));

KRISACHAN avatar May 27 '19 05:05 KRISACHAN

1、节流(throttle)函数的作用是什么?有哪些应用场景,请实现一个节流函数 节流函数:在事件被触发n秒后再执行的回调,如果在这n秒内又重新被触发,则重新开始计时 作用:避免函数频繁调用 区别在于,当事件持续被触发,如果触发时间间隔短于规定的等待时间(n秒),那么 函数防抖的情况下,函数将一直推迟执行,造成不会被执行的效果; 函数节流的情况下,函数将每个 n 秒执行一次 应用场景: 1. window对象的resize、scroll事件 2. 拖拽时的mousemove事件 3. 射击游戏中的mousedown、keydown事件 4. 文字输入、自动完成的keyup事件 实现方式:时间戳或定时器 时间戳 只要触发,就用 Date 获取现在的时间,与上一次的时间比较。 如果时间差大于了规定的等待时间,就可以执行一次; 目标函数执行以后,就更新 previous 值,确保它是“上一次”的时间。 否则就等下一次触发时继续比较

function throttle(func, wait) { let previous = 0; return function() { let now = +new Date(); let context = this;

    if (now - previous >= wait) {
        func.apply(context, arguments);
        previous = now; // 执行后更新 previous 值
    }
}

} eg: container.onmousemove = throttle(doSomething, 1000);

定时器 用定时器实现时间间隔。

当定时器不存在,说明可以执行函数,于是定义一个定时器来向任务队列注册目标函数 目标函数执行后设置保存定时器ID变量为空 当定时器已经被定义,说明已经在等待过程中。则等待下次触发事件时再进行查看。 若要防抖,就马上取消它,重新定义计时器以重新计时 function throttle(func, wait) { let time, context return function(){ context = this if(!time){ time = setTimeout(function(){ func.apply(context, arguments) time = null }, wait) } }

} 效果差异 一个周期内: 时间戳实现的:先执行目标函数,后等待规定的时间段; 计时器实现的:先等待够规定时间,再执行。 即停止触发后,若定时器已经在任务队列里注册了目标函数,它也会执行最后一次。

优化:两者结合 参考 function throttle(func, wait, options) { let time, context, args, result; let previous = 0; if (!options) options = {};

let later = function() { previous = options.leading === false ? 0 : new Date().getTime(); time = null; func.apply(context, args); if (!time) context = args = null; };

let throttled = function() { let now = new Date().getTime(); if (!previous && options.leading === false) previous = now; let remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (time) { clearTimeout(time); time = null; } previous = now; func.apply(context, args); if (!time) context = args = null; } else if (!time && options.trailing !== false) { time = setTimeout(later, remaining); } }; return throttled; } 在 函数防抖(debounce)中,实现了一个 cancel 方法。同理: throttled.cancel = function() { clearTimeout(time); time = null; previous = 0; }

参考 https://github.com/mqyqingfeng/Blog/issues/26 https://blog.csdn.net/beijiyang999/article/details/79836463 emmmm.....手写函数什么的还是需要多练习,只能参考别人的。。

darlingyz avatar May 27 '19 06:05 darlingyz

本题我重点从节流的作用、概念应用场景、手写节流函数方面回答。

一、节流(throttle)的概念

函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,列入水管的水滴在一定的间隔时间滴一滴水。节流是高频触发函数时,但在n秒内也就是约定时间内只会执行一次,节流会稀释函数的执行频率。比如点击发送验证码按钮时,按钮会变成禁用,当到了约定时间比如60秒后按钮才能变成可点击状态,才能再次发送验证码,调用函数。每次触发事件时,如果当前有等待执行的延时函数,则直接return。 image

二、节流的作用

节流就是在一定时间间隔内触发一次事件。在不影响功能的前提下,减少触发事件的频率,提升性能,减少浏览器或者服务器的压力。

三、应用场景

1、滚动页面

2、商品预览图的放大镜效果时,不必每次鼠标移动都计算位置

3、API的调用

4、按钮点击事件/input事件,防止用户多次重复提交

四、手写节流

  • 实现思路 调用函数时,通过上一次pre和现在now两个变量,记录调用时间的频率,prev-now 如果大于约定的时间,才调用函数。调用函数结束后,把pre设置为现在的时间。
 var throttle = function(func, delay) {
            var prev = Date.now();
            return function() {
                var context = this;
                var args = arguments;
                var now = Date.now();
                if (now - prev >= delay) {
                    func.apply(context, args);
                    prev = Date.now();
                }
            }
        }
        function handle() {
            console.log(Math.random());
        }
        window.addEventListener('scroll', throttle(handle, 1000));

五、参考文章

结语 我的回答如有不对的地方,麻烦务必指出来,我及时改正,以免误导别人,让我们共同进步吧!

luohong123 avatar May 27 '19 06:05 luohong123

节流函数的作用:降低函数的调用频率,间隔一段时间执行,防止某一时间频繁触发,减少不必要的计算,不浪费资源; 应用场景:1、元素拖拽功能实现;2、滚动事件;3、鼠标不断点击,单位时间内只触发一次;

/**

  • fn:延时调用函数
  • delay:延迟多长时间
  • mustRun:至少多长时间触发一次 */ function throttle(fn, delay, mustRun){ var timer = null, prev = null return function(){ var now = +new Date(), context = this, args = arguments; if(!prev) prev = now; var wait = now - prev; if(mustRun && wait >= mustRun){ fn.apply(context, args); prev = now }else{ clearTimeout(timer); timer = setTimeout(() => { fn.apply(context, args);
    }, delay); } } }

window.onmousedown = throttle(function(){ console.log(+new Date()) }, 2000, 2000)

Imlona avatar May 27 '19 06:05 Imlona

看到一个总结挺好的,分享下 防抖和节流的区别:函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。

kuroism avatar May 27 '19 07:05 kuroism

节流函数作用

节流函数和防抖函数一样,都是用于处理高频事件的,优化性能。
节流函数是在规定时间段内只执行一次。

节流函数应用场景

1、鼠标点击事件

节流函数实现

/**
 * 节流函数
 * @param fn 延迟执行函数
 * @param delay 延迟时间
 * @param atleast 规定多长时间触发一次
 */
function throttle(fn, delay, atleast) {
    let timer = null;
    let previous = null;
    return function() {
        let context = this, args = arguments;
        let now = +new Date();
        if (!previous) previous = now;
        if (now - previous < atleast) {
            fn.apply(context, args);
            previous = now;
        } else {
            clearTimeout(timer);
            timer = setTimeout(function() {
                fn.apply(context, args)
            }, delay)
        }
    }

}

riluocanyang avatar May 27 '19 08:05 riluocanyang

节流

节流 就是指定时间间隔内 只执行一次

作用

提升性能 避免必要的资源浪费 提高用户体验

场景

重复点击 分页滚动底部的监听比较常见

实现过程

使用时间戳,当触发事件的时候,我们取出当前的时间戳,然后减去之前的时间戳, 如果大于设置的时间周期,就执行函数,然后把时间戳更新为当前的时间戳,如果小于,就不执行 jieliu(fn, delay) { let _arg; let previous = 0; return function(arg) { that = this; _arg = arg; let now = +new Date(); if (now - previous > delay) { fn.call(this, _arg); previous = now; } }; }

zhangxianhui avatar May 27 '19 09:05 zhangxianhui

什么是节流 节流用大白话说就是,在一定的时间周期内这件事儿就只做一次。 以昨天“包治百病”为例,说十天为周期给女朋友买包,如果在这个十天的周期内如果多次要包,怎么着也是不能给买的,要求其严格遵守十天这个期限。如果十天期限一过,女朋友要求买包,这个是肯定可以的。 实际应用 在实际的开发中会有这样一个需求,用户输入查询关键词,点击搜索按钮后提交搜索关键词从服务器获取搜索数据,讲搜索结果展示到页面当中。在这个过程中会有一系列的操作,如数据的提交,关键词匹配,数据查询,数据传输等,这些相对都会占据一定的资源,如果用户的网络不稳定,则会增加查询过程中的等待时间。如果用户等不到自己想要的查询结果就会多次点击i提交按钮,这个时候就需要做节流处理,当用户点击搜索按钮的时候判断数据是否在获取过程中,如果是则不进行搜索提交,如果否则提交关键词,进行搜索。 实现节流 实现节流就需要使用时间戳进行控制,具体实现代码如下:(当然这里也可以参照昨天的防抖设置立即执行和延时执行,这里偷懒了。。。[罪过])

function throttle(fn, ...arg) {
    let run = false;
    return function () {
        if (run) return;
        run = true;
        setTimeout(function () {
            fn.applly(this, arg);
            run = false;
        }, 1000);
    }
}

woyiweita avatar May 27 '19 09:05 woyiweita

背景

事件的触发权很多时候都属于用户,有些情况下会产生问题:

  • 向后台发送数据,用户频繁触发,对服务器造成压力
  • 一些浏览器事件:window.onresize、window.mousemove等,触发的频率非常高,会造成浏览器性能问题如果你碰到这些问题,那就需要用到函数节流和防抖了。

函数节流 (throttle)

  • 一个函数执行一次后,只有大于设定的执行周期后才会执行第二次。 有个需要频繁触发函数,出于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效。

应用场景

需要间隔一定时间触发回调来控制函数调用频率:

  • DOM 元素的拖拽功能实现(mousemove)
  • 搜索联想(keyup)
  • 计算鼠标移动的距离(mousemove)
  • Canvas 模拟画板功能(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

节流函数

function throttle(fn, delay) {
    let pre = 0;
    return function() {
        let now = Date.now();
        if ((now - pre) >= delay) {
            fn.apply(this, arguments);
            pre = now;
        }
    }
}

   function handle() {
            console.log(Math.random());
        }   
        window.addEventListener('scroll', throttle(handle, 1000)); 

ght5935 avatar May 27 '19 09:05 ght5935

概念:函数的节流就是预定一个函数只有在大于等于执行周期时才会执行,周期内调用不会执行。好像一滴水只有积攒到一定重量才会落下一样。 场景:窗口调整(resize)、页面滚动(scroll)、抢购疯狂点击(movedown) function scrollFn(){ console.log(1) } function throttle(method,delay,duration){ var timer=null; var begin=new Date();
return function(){
var context=this, args=arguments; var current=new Date();
clearTimeout(timer); if(current-begin>=duration){ method.apply(context,args); begin=current; }else{ timer=setTimeout(function(){ method.apply(context,args); },delay); } } } window.onscroll=throttle(scrollFn,100,500)

web-data-MrLi avatar May 27 '19 09:05 web-data-MrLi

节流: 指的是高频事件在规定时间内只执行一次,执行一次后,只有大于设定的执行周期后才会执行第二次。 应用场景: 实现dom元素的拖拽功能。 计算鼠标移动的距离。 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次。 `

var processor = { timeoutId: null, //实际进行处理的方法 performProcessing: function(){ //实际执行的代码 }, //初始处理调用的方法 process: function(){ clearTimeout(this.timeoutId); var that = this; this.timeoutId = setTimeout(function(){ that.performProcessing(); }, 100); } }; //尝试开始执行 processor.process(); `

tpxiang avatar May 27 '19 10:05 tpxiang

概念方面先跟前面的防抖区分开。 函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。 函数节流是指一定时间内js方法只跑一次。大于设定的时间再跑第二次。 同样的改变窗口大小的效果,我们看防抖和节流出现的效果有什么不一样。

//防抖
var windowResize = (function (){
    var a = 0;
    return function(){
        a++;
        console.log(a);
    }
})()
$(window).on("resize", _.debounce(windowResize, 300, {
  'leading': false,
  'trailing': true
}))

效果是我在停止拖动浏览器窗口的时候才会触发windowResize 方法。

// 节流
var windowResize = (function (){
    var a = 0;
    return function(){
        a++;
        console.log(a);
    }
})()
$(window).on("resize", _.throttle(windowResize, 300, {
  'leading': false,
  'trailing': true
}))

节流展示的效果更像一个轮询,每隔300ms就会执行一次。在拉动窗口变化执行函数的性能优化上,防抖优于节流

cute1baby avatar May 27 '19 10:05 cute1baby

节流就是在规定的时间间隔内触发一次事件。在不影响功能的前提下,避免一定时间内多次执行某个事件,提升性能,减少浏览器或者服务器的压力。

还是以“包治百病”为例: 节流就是女朋友耍无赖,还特别馋,我不管这10天有没有吃过零食,每隔10天,你就要给我买一次包(败家)。防抖呢:只有连续的10天一次没有吃过零食,才能买一次包,否则每吃一次零食,就从头开始就算天数,哈哈..(尽量找这样的女朋). 应用场景: 实现dom元素的拖拽功能 在页面滚动时判断是否滚动的页面底部,来加载更多 Canvas画笔功能


  function throttle(fn, delay = 500) {
        var prev = Date.now();
        return function () {
            var context = this;
            var args = arguments;
            var now = Date.now();
            if (now - prev >= delay) {
                fn.apply(context, args);
                prev = Date.now();
            }
        }
    }
    window.addEventListener("scroll", function () {
        console.log("对比一下节流")
    })
    window.addEventListener("scroll", throttle(function () {
        console.log("节流:滚动条是否滚动到页面底部")
    }))

0xBrooke avatar May 27 '19 12:05 0xBrooke

节流函数就是固定时间段内只触发一次,比如轮播图的点击,发送短信验证码等

muyiweibo avatar May 27 '19 13:05 muyiweibo

函数节流

含义: 当持续触发事件时,保证一定时间段只调用一次事件处理函数


代码实现

   function throttle (func, delay) {
       let prev = new Date().getTime()
       return function (args) {
           let now = new Date().getTime()
           const that = this
           if (math.floor((now - pre) / 1000) ->delay) {
               func.apply(that, args)
               pre = new Date().getTime()
           }
       }
   }

函数节流保证,一定时间只执行一次函数,当有一些事情需要每隔一段时间就执行的话,节流就可以派上用场了,现实工作中遇到的防抖比较多,节流的反而会少点,这方面体会会比较少

yelin1994 avatar May 27 '19 13:05 yelin1994

函数节流,背后基本思想是指:某些代码不可以没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数请求停止了一段时间之后才执行。


function throttle(fn, context){
 clearTimeout(fn.tId);
 fn.tId = setTimeout(function(){
    fn.apply(context, arguments)
 },200)
}

节流在resize事件中是最常用的,如下案例,设置一个div的高度适中和宽度保持一致 案例:

function resizeDiv(){
  var div = document.getElementById('#myDiv');
  div.style.height = div.offsetWidth + 'px';
}

window.onresize = function(){
  throttle(resizeDiv);
}

kaiking01 avatar May 27 '19 13:05 kaiking01

函数节流:限制函数执行频率,保证函数执行频率不超过设置的值,在保证计算速率要求的情况下节省更多的计算资源。

应用场景:适用于 计算量大,触发时机多 的函数,例如 触发时机为:滚动或者resize,引发重绘 的一类函数。

节流实现:

    function throttle(method, timeout) {
      // 函数执行计时器
      let time;
      // 函数执行计数器
      let count = 0;
      let countTime;

      return function () {
        // 未到时间则直接返回
        if (time) return;
        // 第一次立即执行
        if (count === 0) {
          count++ && method();
          return;
        } else {
          time = setTimeout(() => {
            method();
            clearTimeout(time);
            time = undefined;
            // 一个间隔过后清空执行次数
            countTime && clearTimeout(countTime);
            countTime = setTimeout(() => { count = 0 }, timeout);
          }, timeout);
      }
    }
  };

和防抖的区别:防抖函数有可能一直都不执行,但是节流更加高级一点,除了可以保证多长时间内不会重复执行,还可以保证一定时间内至少可以会执行一次。

XXBeii avatar May 27 '19 13:05 XXBeii

节流函数的作用

节流函数的作用是规定一个单位时间,在这个单位时间内只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。

举例说明:小明的妈妈和小明约定好,如果小明在周考中取得满分,那么当月可以带他去游乐场玩,但是一个月最多只能去一次。

我们来分析一下:

1.如果小明在一个月4次周考中都取得了满分,但是根据约定,他只能去一次游乐场。

2.如果小明一次满分都没有取得,他没有去游乐场的机会。

3.如果小明一月取得3次满分,那么一月份他可以去一次游乐场,但是二月一次满分都没有,二月他不能去游乐场。

这其实就是一个节流的例子,在一个月的时间内,去游乐场最多只能触发一次。即使这个时间周期内,小明取得多次满分。

节流应用场景

按钮点击事件 拖拽事件 onScoll 计算鼠标移动的距离(mousemove)

节流函数实现

function throttle (func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function () {
        previous = options.leading === false ? 0 : Date.now() || new Date().getTime();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };

    var throttled = function () {
        var now = Date.now() || new Date().getTime();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            // 判断是否设置了定时器和 trailing
            timeout = setTimeout(later, remaining);
        }
        return result;
    };

    throttled.cancel = function () {
        clearTimeout(timeout);
        previous = 0;
        timeout = context = args = null;
    };

    return throttled;
}

YvetteLau avatar May 27 '19 13:05 YvetteLau

节流函数的作用: 在事件频繁触发的情况下,每隔一段时间,只执行一次回调函数,避免产生性能问题。

应用场景:

  • 滚动加载,加载更多或滚到底部监听
  • 谷歌搜索框,搜索联想功能
  • 高频点击提交,表单重复提交

实现:

function throttle(fn, delay) {
    var timer;
    return function () {
        var _this = this;
        var args = arguments;
        if (timer) {
            return;
        }
        timer = setTimeout(function () {
            fn.apply(_this, args);
            timer = null;
        }, delay)
    }
}

huangsiyuan2015 avatar May 27 '19 14:05 huangsiyuan2015

节流指的是每隔一段时间,执行一次事件。在时间范围内,不管我们怎么去触发这个事件,实际上只会触发一次。 应用场景常见的有懒加载 实现节流的方式有两种,一是时间戳,二是定时器。 1,使用时间戳的方式:

`function throttle(func, wait) { var context, args; var previous = 0;

return function() {
    var now = +new Date();
    context = this;
    args = arguments;
    if (now - previous > wait) {
        func.apply(context, args);
        previous = now;
    }
}

}`

2,使用定时器的方式

`function throttle(func, wait) { var timeout; var previous = 0;

return function() {
    context = this;
    args = arguments;
    if (!timeout) {
        timeout = setTimeout(function(){
            timeout = null;
            func.apply(context, args)
        }, wait)
    }

}

}`

plane-hjh avatar May 27 '19 14:05 plane-hjh

  • 作用:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行,可以提升性能,减少浏览器或者服务器的压力。
/**
* @param fn {Function} 实际要执行的函数
* @param interval {Number} 延迟时间,默认 300 毫秒
* 
* @return {Function} 
*/

function throttle(fn, interval = 3000) {
   let canRun = true;
   return function () {
       if (!canRun) return;
       canRun = false;
       setTimeout(() => {
           fn.apply(this, arguments);
           canRun = true;
       }, interval)
   }
}

ccvaille avatar May 27 '19 14:05 ccvaille

节流就是不管事件连续触发多少次,我只在固定的时间过后,执行后面的方法。 还是下面这篇文章,后续还是要再看看。还是要今日事今日毕。 缺太多,补起来好累啊。 https://segmentfault.com/a/1190000018205319?utm_source=tag-newest

jodiezhang avatar May 27 '19 15:05 jodiezhang

在这里我再写写防抖和节流的概念 防抖

防抖就是规定的时间内执行一次,分为立即执行和非立即执行,如果规定的时间内再次触发,那么事件是不会被触发的 节流

节流就很理解,就是每隔一定的时间执行一次。 有时间戳和定时器两种方法

时间戳

thorttle(func,delay){
     let prev = Date.now();
        return fucntion(){
            let context = this;
            let args = arguments;
            let now = Date.bow();
                if(now-prev>=delay){
                    func.apply(context,args);
                    prev = Date.now()
                }
            }    
     }

定时器

 function thorttle(func,delay){
     let timer = null;
        return function(){
            let context = this;
            let args= arguments;
            if(!timer){
                timer= setTimeout(()=>{
                func.apply(context,args);
                timer = null;
                },delay)
            }
        }
   }

虽然参考了别人的代码,但是是自己手敲的,印象就多了一分

MissNanLan avatar May 27 '19 15:05 MissNanLan

在JS中,mousemove 和滚动是会不间断的触发的 函数节流的基本思想是设置一个定时器,在指定时间间隔内运行代码时清除上一次的定时器,并设置另一个定时器,直到函数请求停止并超过时间间隔才会执行。 在javascript高级程序设计 例子如下: function scrollFn(){ console.log(1) } function throttle(method,delay,duration){ var timer=null; var begin=new Date();
return function(){
var context=this, args=arguments; var current=new Date();
clearTimeout(timer); if(current-begin>=duration){ method.apply(context,args); begin=current; }else{ timer=setTimeout(function(){ method.apply(context,args); },delay); } } } window.onscroll=throttle(scrollFn,100,500)

clairing avatar May 28 '19 01:05 clairing

节流、是指函数在指定的时间间隔内只执行一次,执行期间再次调用会被无视。等本次调用完等待下一次调用。

jizx avatar May 28 '19 01:05 jizx

节流是为了防止事件的频繁书法的一种方式,常用的事件包括

  • 滚动加载,加载更多或滚到底部监听
  • resize事件,鼠标事件,onmouseover,按钮点击事件
  • 一般有两种方式:时间戳,定时器方式实现。

function throttle(func,delay){ var arg = argument; var context = this; var timer = null; if(!timer){ timer = settimeout(()=>{ func.apply(arg,context); timer = null; },delay) }} function handle() { console.log(Math.random()); } window.addEventListener('scroll', throttle(handle, 1000));

Liruimin2 avatar May 28 '19 01:05 Liruimin2

1.节流函数的作用: 预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。 2.应用场景: (1)DOM元素的拖拽功能实现(mousemove) (2)射击游戏的mousedown/keydown事件(单位时间只能发射一颗子弹) (3)计算鼠标移动的距离(mousemove) (4)Canvas模拟画板功能(mousemove) (5)搜索联想(keyup) (6)监听滚动事件判断是否到页面底部自动加载更多:给scroll加了debounce后,只有用户停止滚动后,才会判断是否到了页面底部;如果是throttle的花,只要页面滚动就会间隔一段时间判断一次 (7)click事件(不停快速点击按钮,减少触发频次) (8)scroll事件(返回顶部按钮出现\隐藏事件触发) (9)keyup事件(输入框文字与显示栏内容复制同步) (10)减少发送ajax请求,降低请求频率 3.实现节流函数 function scrollFn(){ console.log(1) } function throttle(method,delay,duration){ var timer=null; var begin=new Date();
return function(){
var context=this, args=arguments; var current=new Date();
clearTimeout(timer); if(current-begin>=duration){ method.apply(context,args); begin=current; }else{ timer=setTimeout(function(){ method.apply(context,args); },delay); } } } window.onscroll=throttle(scrollFn,100,500)

(微信名:RUN)

MissWXiang avatar May 28 '19 02:05 MissWXiang