函数防抖与节流[转载]

underscore.js提供了很多很有用的函数,两个函数都用于限制函数的执行。

debounce

在解释这个函数前,我们先从一个例子看下这个函数的使用场景。假设我们网站有个搜索框,用户输入文本我们会自动联想匹配出一些结果供用户选择。我们可能首先想到的做法就是监听keypress事件,然后异步去查询结果。这个方法本身是没错的,但是如果用户快速的输入了一连串的字符,假设是10个字符,那么就会在瞬间触发了10次的请求,这无疑不是我们想要的。我们想要的是用户停止输入的时候才去触发查询的请求,这时候函数防抖可以帮到我们。

函数防抖就是让某个函数在上一次执行后,满足等待某个时间内不再触发此函数后再执行,而在这个等待时间内再次触发此函数,等待时间会重新计算。

我们先看下underscore.js里相关函数的定义:

_.debounce(function, wait, [immediate])

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
  var timeout, args, context, timestamp, result;

  var later = function() {
    var last = _.now() - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function() {
    context = this;
    args = arguments;
    timestamp = _.now();
    var callNow = immediate && !timeout;
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };
};

参数function是需要进行函数防抖的函数;参数wait则是需要等待的时间,单位为毫秒;immediate参数如果为true,则debounce函数会在调用时立刻执行一次function,而不需要等到wait这个时间后,例如防止点击提交按钮时的多次点击就可以使用这个参数。

所以,上面那个场景,我们可以这么解决:

function query() {
  //进行异步调用查询
}

var lazyQuery = _.debounce(query, 300);
$(‘#search‘).keypress(lazyQuery);

throttle

我们网站经常会有这样的需求,就是滚动浏览器滚动条的时候,更新页面上的某些布局内容或者去调用后台的某接口查询内容。同样的,如果不对函数调用的频率加以限制的话,那么可能我们滚动一次滚动条就会产生N次的调用了。但是这次的情况跟上面的有所不同,我们不是要在每完成等待某个时间后去执行某函数,而是要每间隔某个时间去执行某函数,避免函数的过多执行,这个方式就叫函数节流

同样的,我们看下underscore.js里相关函数的定义:

_.throttle(function, wait, [options])

// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you‘d like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function() {
    previous = options.leading === false ? 0 : _.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function() {
    var now = _.now();
    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) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
};

参数function是需要进行函数节流的函数;参数wait则是函数执行的时间间隔,单位是毫秒。option有两个选项,throttle第一次调用时默认会立刻执行一次function,如果传入{leading: false},则第一次调用时不执行function。{trailing: false}参数则表示禁止最后那一次延迟的调用。具体可以看源码进行理解。

所以,在滚动滚动条的场景,我们可以这么做:

function handleScroll() {
  //进行滚动时的相关处理
}

var throttled = _.throttle(handleScroll, 100);
$(window).scroll(throttled);

参考

http://underscorejs.org/#debounce
http://underscorejs.org/#throttle

原文 http://segmentfault.com/a/1190000002764479

时间: 2024-08-24 10:08:43

函数防抖与节流[转载]的相关文章

前端进击的巨人(八):浅谈函数防抖与节流

本篇课题,或许早已是烂大街的解读文章.不过春招系列面试下来,不少伙伴们还是似懂非懂地栽倒在(-面试官-)深意的笑容之下,权当温故知新. JavaScript的执行过程,是基于栈来进行的.复杂的程序代码被封装到函数中,程序执行时,函数不断被推入执行栈中.所以 "执行栈" 也称 "函数执行栈". 函数中封装的代码块,一般都有相对复杂的逻辑处理(计算/判断),例如函数中可能会涉及到 DOM 的渲染更新,复杂的计算与验证, Ajax 数据请求等等. 前端页面的操作权,大部分

vue函数防抖和节流

Vue函数防抖和节流https://zhuanlan.zhihu.com/p/72363385 <template> <div> <input type='text' v-model='value' @keydown = "hangleChange"> </div> </template> <script> function debounce(func, wait=1000){ let timeout; retur

javaScript基本功之函数防抖与节流

1.函数节流与防抖 函数的节流与防抖是一种优化频繁调用时优化的方案. 比如canvas画笔时频繁获取位置点绘画会增大客服端CPU压力,那么就需要那控制频繁操作为一个范围内来优化而不影响绘画效果, 这样能让页面浏览更加顺畅,不会因为js的执行而发生卡顿. 函数节流是指一定时间内js方法只调用一次.比如人的眨眼睛,就是一定时间内眨一次.这是函数节流最形象的解释.函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次.比如生活中的坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车.

函数防抖与节流

1.为什么会有函数的防抖与节流及使用场景 在进行窗口的resize.scroll,输入框内容校验或者向后端发起ajax等操作时, 如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕. 此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果. 2.函数防抖与函数节流的概念及实现原理 函数防抖(debounce): 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了

函数防抖和节流*(性能优化不错的选择)

函数节流: 频繁触发,但只在特定的时间内才执行一次代码 函数防抖: 频繁触发,但只在特定的时间内没有触发执行条件才执行一次代码(如果一个事件被频繁触发多次,节流函数可以按照固定频率去执行对应的事件处理方法) 两者区别在于函数节流是固定时间做某一件事,比如每隔1秒发一次请求.而函数防抖是在频繁触发后,只执行一次(两者的前提都是频繁触发) 函数节流的应用场景一般是onrize,onscroll等这些频繁触发的函数,比如你想获取滚动条的位置,然后执行下一步动作,如果监听后执行的是Dom操作,这样的频繁

函数防抖和节流的结合

函数节流有个毛病,就是最后一次事件执行后,如果距离上一次事件执行不到规定时间,那么最后一次事件就不会执行,解决方法就是把事件函数节流和防抖结合在一起 function throlle(callback,delay){ let startTime=0; let timer=null; return function (){ //使用new Date().getTime(),这样首次操作一定会执行 let endTime=new Date().getTime(); clearTimeout(time

函数防抖和节流

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)

Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 你们的 star 是我学习的动力!GitHub 地址 本文涉及知识点: 防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 TCP 三次握手与四次挥手 浏览器渲染页面 在本文中,jsliang 会讲解通过自我探索后关于上述知识点的个人理解,如有纰漏.疏忽或者误解,欢迎各位小伙伴留言指出. 如果小伙伴对文章存有疑问,想快速得到回复. 或者小伙伴对 jsliang 个人的前端文档库感兴趣,也想将自己的前端知识整理出来. 欢迎

JS 函数防抖和函数节流

我们都知道频繁触发执行一段js逻辑代码对性能会有很大的影响,尤其是在做一些效果实现方面,或者逻辑中需要进行后端请求,更是会导致卡顿,效果失效等结果,所以在处理类似的情况时,可以考虑使用函数节流和函数去抖来解决,至于具体使用哪一种方式,根据实际情况分析定夺,先来讲解一些这两者的概念 函数节流:在频繁触发的情况下,需要执行的逻辑只有执行完之后,才能继续执行下一次 函数防抖:在频繁触发的情况下,只有足够的空闲时间,才执行代码一次,如果没有执行完就清除掉,重新执行逻辑 应用场景:高频触发以下方法 页面滚