在JavaScript里防止事件函数高频触发和高频调用的方法


Posted in Javascript onSeptember 06, 2014

网页中JavaScript最基本的功能是监听或响应用户的动作,这非常的有用。用户的动作有些频率非常高,有的十分罕见。有些监听器函数的执行如闪电般完成,而有些繁重的会把浏览器拖死。拿浏览器窗口的resize事件来说,这种事件会在浏览器窗口大小的每一尺度变化都触发一次,如果监听器体量很大,你的浏览器很快就会被拖垮。

很显然,我们不能允许浏览器被拖垮,但我们又不能删除删除监听器。然而,我们可以限制函数调用的频度,弱化事件函数运行带来的影响。相对于让窗口的每一步size的变化都触发一次监听器函数,我们可以现在监听函数的触发的最小间隔必须大于多少毫秒,让它保持着合理的调用频道,确保不毁坏用户体验。有一个很好的js工具库叫做Underscore.js,它里面有一个简单的方法能让你轻松的创建降低事件函数触发频度的监听器。

JavaScript代码

降频监听器的代码很简单:

// 创建监听器

var updateLayout = _.debounce(function(e) {
 // Does all the layout updating here
}, 500); // 最低500毫秒运行一次
// Add the event listener

window.addEventListener("resize", updateLayout, false);

…这段Underscore.js代码底层实际上是用interval检查事件函数调用的频度:
// 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;

 return function() {

  var context = this, args = arguments;

  var later = function() {

   timeout = null;

   if (!immediate) func.apply(context, args);

  };

  var callNow = immediate && !timeout;

  clearTimeout(timeout);

  timeout = setTimeout(later, wait);

  if (callNow) func.apply(context, args);

 };

};

代码并不是特别复杂,但用不着自己写也是一种幸福。这个debounce函数并没有依赖其他的Underscore.js函数,所以,你可以把这个方法添加到你喜欢的js工具库中,例如jQuery或MooTools,很容易:
// MooTools

Function.implement({

 debounce: function(wait, immediate) {

  var timeout, 

      func = this;

  return function() {

   var context = this, args = arguments;

   var later = function() {

    timeout = null;

    if (!immediate) func.apply(context, args);

   };

   var callNow = immediate && !timeout;

   clearTimeout(timeout);

   timeout = setTimeout(later, wait);

   if (callNow) func.apply(context, args);

  };

 }

});
// Use it!

window.addEvent("resize", myFn.debounce(500));

正如上面说的,窗口的resize事件是最常见的使用降频操作的地方,还有一个常用的地方是,根据用户的按键输入给出自动补全提示。我非常喜欢收集这样的代码片段,它们能轻松的让你的网站更高效。同时也推荐大家研究一下Underscore.js,里面提供了大量非常有用的函数。
Javascript 相关文章推荐
JavaScript CSS修改学习第三章 修改样式表
Feb 19 Javascript
JQuery 自定义CircleAnimation,Animate方法学习笔记
Jul 10 Javascript
js中页面的重新加载(当前页面/上级页面)及frame或iframe元素引用介绍
Jan 24 Javascript
JS求平均值的小例子
Nov 29 Javascript
jQuery html()方法使用不了无法显示内容的问题
Aug 06 Javascript
用js动态添加html元素,以及属性的简单实例
Jul 19 Javascript
JQuery遍历元素的父辈和祖先的方法
Sep 18 Javascript
JS实现向iframe中表单传值的方法
Mar 24 Javascript
JavaScript实现的DOM绘制柱状图效果示例
Aug 08 Javascript
详解vue+axios给开发环境和生产环境配置不同的接口地址
Aug 16 Javascript
微信小程序自定义菜单切换栏tabbar组件代码实例
Dec 30 Javascript
Vant 在vue-cli 4.x中按需加载操作
Nov 05 Javascript
js获取页面传来参数的方法
Sep 06 #Javascript
用javascript关闭本窗口技巧小结
Sep 05 #Javascript
使用jquery解析XML示例代码
Sep 05 #Javascript
js实现按一下删除键删除整个单词附demo
Sep 05 #Javascript
JS获取当前网页大小以及屏幕分辨率等
Sep 05 #Javascript
JS来动态的修改url实现对url的增删查改
Sep 05 #Javascript
jQuery表格插件datatables用法总结
Sep 05 #Javascript
You might like
php class中public,private,protected的区别以及实例分析
2013/06/18 PHP
PHP删除数组中特定元素的两种方法
2013/07/02 PHP
php实现的常见排序算法汇总
2014/09/08 PHP
thinkPHP中验证码的简单使用方法
2015/12/26 PHP
php自定义函数实现JS的escape的方法示例
2016/07/07 PHP
删除PHP数组中的重复元素的实现代码
2017/04/10 PHP
php post json参数的传递和接收处理方法
2018/05/31 PHP
PHP利用curl发送HTTP请求的实例代码
2020/07/09 PHP
用js实现预览待上传的本地图片
2007/03/15 Javascript
理解JavaScript变量作用域更轻松
2009/10/25 Javascript
实现一个简单的vue无限加载指令方法
2017/01/10 Javascript
jQuery基于ajax实现页面加载后检查用户登录状态的方法
2017/02/10 Javascript
JavaScript表单验证的两种实现方法
2017/02/11 Javascript
详解Vue学习笔记入门篇之组件的内容分发(slot)
2017/07/17 Javascript
微信小程序 同步请求授权的详解
2017/08/04 Javascript
Angular中管道操作符(|)的使用方法
2017/12/15 Javascript
vue模式history下在iis中配置流程
2019/04/17 Javascript
微信小程序云开发如何实现数据库自动备份实现
2019/08/16 Javascript
Python中Class类用法实例分析
2015/11/12 Python
python 执行shell命令并将结果保存的实例
2018/05/11 Python
对PyQt5中的菜单栏和工具栏实例详解
2019/06/20 Python
sklearn-SVC实现与类参数详解
2019/12/10 Python
用python写PDF转换器的实现
2020/10/29 Python
Traffic People官网:女式花裙、上衣和连身裤
2020/10/12 全球购物
军训自我鉴定100字
2014/02/13 职场文书
给老婆大人的检讨书
2014/02/24 职场文书
美丽乡村建设实施方案
2014/03/23 职场文书
安全标语大全
2014/06/10 职场文书
授权委托书范文
2014/07/31 职场文书
付款委托书范本
2014/10/05 职场文书
2014年客服工作总结范文
2014/11/13 职场文书
MySQL Innodb关键特性之插入缓冲(insert buffer)
2021/04/08 MySQL
PHP使用非对称加密算法RSA
2021/04/21 PHP
【海涛dota】偶遇拉娜娅 质量局德鲁伊第一视角解说
2022/04/01 DOTA
Go gRPC进阶教程gRPC转换HTTP
2022/06/16 Golang
MySQL性能指标TPS+QPS+IOPS压测
2022/08/05 MySQL