电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

瀏覽:80日期:2023-10-06 16:23:44

問(wèn)題的引出

在一些場(chǎng)景往往由于事件頻繁被觸發(fā),因而頻繁地進(jìn)行DOM操作、資源加載,導(dǎo)致UI停頓甚至瀏覽器崩潰。

在這樣的情況下,我們實(shí)際上的需求大多為停止改變大小n毫秒后執(zhí)行后續(xù)處理;而其他事件大多的需求是以一定的頻率執(zhí)行后續(xù)處理。針對(duì)這兩種需求就出現(xiàn)了debounce和throttle兩種解決辦法。

1. resize事件

2. mousemove事件

3. touchmove事件

4.scroll事件

throttle 與 debounce

在現(xiàn)在很多的javascript框架中都提供了這兩個(gè)函數(shù)。例如 jquery中有throttle和debounce插件, underscore.js ,Lodash.js 等都提供了這兩個(gè)函數(shù)。

原理:

首先我們會(huì)想到設(shè)置一定的時(shí)間范圍delay,每隔delayms 執(zhí)行不超過(guò)一次。

事件處理函數(shù)什么時(shí)候執(zhí)行能? 這里有兩個(gè)選擇,一是先執(zhí)行,再間隔delayms來(lái)等待;或者是先等待delayms,然后執(zhí)行事件處理函數(shù)。

操作過(guò)程中的事件全不管,反正只執(zhí)行一次事件處理。

相同低,這一次的事件處理可以是先執(zhí)行一次,然后后面的事件都不管; 或者前面的都不管,最后操作完了再執(zhí)行一次事件處理。

區(qū)別:

1. throttle

如果將水龍頭擰緊直到水是以水滴的形式流出,那你會(huì)發(fā)現(xiàn)每隔一段時(shí)間,就會(huì)有一滴水流出。

也就是會(huì)說(shuō)預(yù)先設(shè)定一個(gè)執(zhí)行周期,當(dāng)調(diào)用動(dòng)作的時(shí)刻大于等于執(zhí)行周期則執(zhí)行該動(dòng)作,然后進(jìn)入下一個(gè)新周期。

2.debounce

如果用手指一直按住一個(gè)彈簧,它將不會(huì)彈起直到你松手為止。

也就是說(shuō)當(dāng)調(diào)用動(dòng)作n毫秒后,才會(huì)執(zhí)行該動(dòng)作,若在這n毫秒內(nèi)又調(diào)用此動(dòng)作則將重新計(jì)算執(zhí)行時(shí)間。

簡(jiǎn)單代碼實(shí)現(xiàn)及實(shí)驗(yàn)結(jié)果

那么下面我們自己簡(jiǎn)單地實(shí)現(xiàn)下這兩個(gè)函數(shù):

throttle 函數(shù):

window.addEventListener('resize', throttle(callback, 300, {leading:false})); window.addEventListener('resize', callback2); function callback () { console.count('Throttled'); } function callback2 () { console.count('Not Throttled'); } /** * 頻率控制函數(shù), fn執(zhí)行次數(shù)不超過(guò) 1 次/delay * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時(shí)間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */ function throttle(fn,delay,options) { var wait=false; if (!options) options = {}; return function(){ var that = this,args=arguments; if(!wait){ if (!(options.leading === false)){ fn.apply(that,args); } wait=true; setTimeout(function () { if (!(options.trailing === false)){ fn.apply(that,args); } wait=false; },delay); } } }

將以上代碼貼入瀏覽器中運(yùn)行,可得到:

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

下面再看debounce函數(shù)的情況,

debounce 函數(shù):

window.addEventListener('resize', throttle(callback, 300, {leading:false}));window.addEventListener('resize', callback2);function callback () { console.count('Throttled'); }function callback2 () { console.count('Not Throttled'); }/** * 空閑控制函數(shù), fn僅執(zhí)行一次 * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時(shí)間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */function debounce(fn, delay, options) { var timeoutId; if (!options) options = {}; var leadingExc = false; return function() { var that = this, args = arguments; if (!leadingExc&&!(options.leading === false)) { fn.apply(that, args); } leadingExc=true; if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(function() { if (!(options.trailing === false)) {fn.apply(that, args); } leadingExc=false; }, delay); }}

將以上代碼貼入瀏覽器中運(yùn)行,分三次改變窗口大小,可看到,每一次改變窗口的大小都會(huì)把開始和結(jié)束邊界的事件處理函數(shù)各執(zhí)行一次:

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

如果是一次性改變窗口大小,會(huì)發(fā)現(xiàn)開始和結(jié)束的邊界各執(zhí)行一次時(shí)間處理函數(shù),請(qǐng)注意與一次性改變窗口大小時(shí) throttle 情況的對(duì)比:

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

underscore.js 的代碼實(shí)現(xiàn)

_.throttle函數(shù)

/** * 頻率控制函數(shù), fn執(zhí)行次數(shù)不超過(guò) 1 次/delay * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時(shí)間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */_.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) { 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; };};

_.debounce函數(shù)

/** * 空閑控制函數(shù), fn僅執(zhí)行一次 * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時(shí)間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */_.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; };};

參考的文章

Debounce and Throttle: a visual explanationjQuery throttle / debounce: Sometimes, less is more!underscore.js

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 东莞市天进机械有限公司-钉箱机-粘箱机-糊箱机-打钉机认准东莞天进机械-厂家直供更放心! | 中高频感应加热设备|高频淬火设备|超音频感应加热电源|不锈钢管光亮退火机|真空管烤消设备 - 郑州蓝硕工业炉设备有限公司 | 长江船运_国内海运_内贸船运_大件海运|运输_船舶运输价格_钢材船运_内河运输_风电甲板船_游艇运输_航运货代电话_上海交航船运 | 网站优化公司_北京网站优化_抖音短视频代运营_抖音关键词seo优化排名-通则达网络 | 团建-拓展-拓展培训-拓展训练-户外拓展训练基地[无锡劲途] | 聚氨酯催化剂K15,延迟催化剂SA-1,叔胺延迟催化剂,DBU,二甲基哌嗪,催化剂TMR-2,-聚氨酯催化剂生产厂家 | 汽车整车综合环境舱_军标砂尘_盐雾试验室试验箱-无锡苏南试验设备有限公司 | 环球周刊网| X光检测仪_食品金属异物检测机_X射线检测设备_微现检测 | 齿辊分级破碎机,高低压压球机,立式双动力磨粉机-郑州长城冶金设备有限公司 | 【德信自动化】点胶机_全自动点胶机_自动点胶机厂家_塑料热压机_自动螺丝机-深圳市德信自动化设备有限公司 | 直齿驱动-新型回转驱动和回转支承解决方案提供商-不二传动 | 密度电子天平-内校-外校电子天平-沈阳龙腾电子有限公司 | 酒吧霸屏软件_酒吧霸屏系统,酒吧微上墙,夜场霸屏软件,酒吧点歌软件,酒吧互动游戏,酒吧大屏幕软件系统下载 | 苏州柯瑞德货架-仓库自动化改造解决方案 | 西安展台设计搭建_西安活动策划公司_西安会议会场布置_西安展厅设计西安旭阳展览展示 | 超声波成孔成槽质量检测仪-压浆机-桥梁预应力智能张拉设备-上海硕冠检测设备有限公司 | 意大利Frascold/富士豪压缩机_富士豪半封闭压缩机_富士豪活塞压缩机_富士豪螺杆压缩机 | 厂房出租-厂房规划-食品技术-厂房设计-厂房装修-建筑施工-设备供应-设备求购-龙爪豆食品行业平台 | 糖衣机,除尘式糖衣机,全自动糖衣机,泰州市长江制药机械有限公司 体感VRAR全息沉浸式3D投影多媒体展厅展会游戏互动-万展互动 | 深圳法律咨询【24小时在线】深圳律师咨询免费 | 12cr1mov无缝钢管切割-15crmog无缝钢管切割-40cr无缝钢管切割-42crmo无缝钢管切割-Q345B无缝钢管切割-45#无缝钢管切割 - 聊城宽达钢管有限公司 | 贝朗斯动力商城(BRCPOWER.COM) - 买叉车蓄电池上贝朗斯商城,价格更超值,品质有保障! | 组织研磨机-高通量组织研磨仪-实验室多样品组织研磨机-东方天净 传递窗_超净|洁净工作台_高效过滤器-传递窗厂家广州梓净公司 | 涂层测厚仪_光泽度仪_uv能量计_紫外辐照计_太阳膜测试仪_透光率仪-林上科技 | 智能监控-安防监控-监控系统安装-弱电工程公司_成都万全电子 | 真丝围巾|真丝丝巾|羊绒围巾|围巾品牌|浙江越缇围巾厂家定制 | 长沙印刷厂-包装印刷-画册印刷厂家-湖南省日大彩色印务有限公司 青州搬家公司电话_青州搬家公司哪家好「鸿喜」青州搬家 | 丹佛斯变频器-丹佛斯压力开关-变送器-广州市风华机电设备有限公司 | 深圳货架厂家_金丽声精品货架_广东金丽声展示设备有限公司官网 | 国际学校_国际学校哪个好_国际课程学校-国际学校择校网 | 首页-浙江橙树网络技术有限公司 石磨面粉机|石磨面粉机械|石磨面粉机组|石磨面粉成套设备-河南成立粮油机械有限公司 | 净化板-洁净板-净化板价格-净化板生产厂家-山东鸿星新材料科技股份有限公司 | 胶泥瓷砖胶,轻质粉刷石膏,嵌缝石膏厂家,腻子粉批发,永康家德兴,永康市家德兴建材厂 | 沈阳网站建设_沈阳网站制作_沈阳网页设计-做网站就找示剑新零售 沈阳缠绕膜价格_沈阳拉伸膜厂家_沈阳缠绕膜厂家直销 | 缠绕机|缠绕膜包装机|缠绕包装机-上海晏陵智能设备有限公司 | 单螺旋速冻机-双螺旋-流态化-隧道式-食品速冻机厂家-广州冰泉制冷 | 菲希尔FISCHER测厚仪-铁素体检测仪-上海吉馨实业发展有限公司 | 背压阀|减压器|不锈钢减压器|减压阀|卫生级背压阀|单向阀|背压阀厂家-上海沃原自控阀门有限公司 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 济南宣传册设计-画册设计_济南莫都品牌设计公司 | 课件导航网_ppt课件_课件模板_课件下载_最新课件资源分享发布平台 |