淺談JavaScript節(jié)流與防抖
節(jié)流與防抖
背景:當(dāng)我們頻繁去請(qǐng)求資源、接口等其他的時(shí)候,就會(huì)造成操作Dom頻繁,接口壓力大等等,性能下降。比如我有時(shí)候會(huì)每次搜索會(huì)猛地敲回車,在網(wǎng)絡(luò)不很好的時(shí)候,點(diǎn)擊下一頁按鈕的時(shí)候也會(huì)一直點(diǎn),可能網(wǎng)絡(luò)不好也可能服務(wù)器性能低。
為了避免頻繁觸發(fā)同一事件或請(qǐng)求,這時(shí)候就要用到節(jié)流和防抖了。
what?這是啥?當(dāng)我第一次聽到這兩個(gè)名字的時(shí)候,心想是指節(jié)省流量、防止手抖嗎。百思不得其解,趕緊就去學(xué)習(xí)。
概念:
簡單來說:節(jié)流和防抖就是為了防止事件在短時(shí)間內(nèi)多次觸發(fā)的兩種解決方案。都是用過減少請(qǐng)求的次數(shù),來降低壓力,提高性能。
區(qū)別
節(jié)流:在一定的時(shí)間內(nèi)只會(huì)請(qǐng)求一次。
可以理解為:公交車,每個(gè)人是一次點(diǎn)擊請(qǐng)求,每十分鐘開一趟車,發(fā)送請(qǐng)求
防抖:觸發(fā)事件后n秒后才能執(zhí)行函數(shù),如果在n秒內(nèi)觸發(fā)了事件,則會(huì)重新計(jì)算執(zhí)行時(shí)間。
比如在一段時(shí)間內(nèi),我一直點(diǎn)擊按鈕,以最后一次點(diǎn)擊為準(zhǔn)發(fā)送一次請(qǐng)求。
節(jié)流實(shí)現(xiàn)
解決思路 :
使用時(shí)間戳(發(fā)生在一段時(shí)間的開始),就是在計(jì)算
當(dāng)前點(diǎn)擊的時(shí)間 - 上一次執(zhí)行函數(shù)的時(shí)間 > 我設(shè)定的時(shí)間戳 ,就執(zhí)行一次函數(shù)
缺點(diǎn):第一次直接觸發(fā) 最后一次一段時(shí)間內(nèi)無法觸發(fā)
給一個(gè)場景,當(dāng)我們搜索數(shù)據(jù)的時(shí)候,發(fā)起請(qǐng)求,沒有做處理是這樣的,請(qǐng)求肯定太過于頻繁
節(jié)流函數(shù)
代碼:
<body> <div> <span>節(jié)流處理</span><input id="input" type="text"> <button id="btn">請(qǐng)求</button> </div> </body> <script> var btn = document.getElementById("btn") btn.addEventListener("click", throttle(output, 1000)) //添加點(diǎn)擊事件監(jiān)聽 function output(e) { console.log(this, e) console.log(document.getElementById("input").value) //模擬發(fā)起一次請(qǐng)求 } //節(jié)流函數(shù) function throttle(fn, delay) { // fn為執(zhí)行的函數(shù),delay為延遲時(shí)間 var last = 0; //上一次結(jié)束的時(shí)間 return function () { var cur = Date.now() console.log(cur-last) if (cur - last > delay) { fn.apply(this, arguments) //執(zhí)行函數(shù) last = cur //更新上一次時(shí)間 } } } </script>
效果:
防抖實(shí)現(xiàn)
解決思路 :
定時(shí)器(發(fā)生在定時(shí)結(jié)束)。缺點(diǎn):第一次不觸發(fā) 最后一次延遲觸發(fā)
就是設(shè)置一個(gè)定時(shí)器,如果一直點(diǎn)擊則清除定時(shí)器,最后一次開啟定時(shí)器
防抖函數(shù)
代碼:
<body> <div> <span>防抖處理</span><input id="input" type="text"> <button id="btn">請(qǐng)求</button> </div> </body> <script> var btn = document.getElementById("btn") btn.addEventListener("click", debounce(output, 1000)) //添加點(diǎn)擊事件監(jiān)聽 function output(e) { console.log(this, e) console.log(document.getElementById("input").value) //模擬發(fā)起一次請(qǐng)求 } function debounce(fn, delay) { // fn為執(zhí)行的函數(shù),delay為延遲時(shí)間 var time = null; //定時(shí)器 return function () { clearTimeout(time); //清除定時(shí)器 let context = this; //獲取當(dāng)前button上下文 如果不指定,箭頭函數(shù)就會(huì)一直往外找到window let args = arguments; time = setTimeout(() => { fn.apply(context, args); }, delay); } } </script>
效果:
防抖升級(jí)版
第一次觸發(fā)和最后一次延遲觸發(fā)
代碼:
function throttle(fn, delay) { // fn為執(zhí)行的函數(shù),delay為延遲時(shí)間 let time = null let flag=true //標(biāo)識(shí)是不是第一次觸發(fā) return function () { clearTimeout(time) if (flag) { fn.apply(this, arguments) flag=false } time = setTimeout(() => { //觸發(fā)定時(shí)器 fn.apply(this, arguments) flag=true }, delay) } }
效果:
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
節(jié)流與防抖
背景:當(dāng)我們頻繁去請(qǐng)求資源、接口等其他的時(shí)候,就會(huì)造成操作Dom頻繁,接口壓力大等等,性能下降。比如我有時(shí)候會(huì)每次搜索會(huì)猛地敲回車,在網(wǎng)絡(luò)不很好的時(shí)候,點(diǎn)擊下一頁按鈕的時(shí)候也會(huì)一直點(diǎn),可能網(wǎng)絡(luò)不好也可能服務(wù)器性能低。
為了避免頻繁觸發(fā)同一事件或請(qǐng)求,這時(shí)候就要用到節(jié)流和防抖了。
what?這是啥?當(dāng)我第一次聽到這兩個(gè)名字的時(shí)候,心想是指節(jié)省流量、防止手抖嗎。百思不得其解,趕緊就去學(xué)習(xí)。
概念:
簡單來說:節(jié)流和防抖就是為了防止事件在短時(shí)間內(nèi)多次觸發(fā)的兩種解決方案。都是用過減少請(qǐng)求的次數(shù),來降低壓力,提高性能。
區(qū)別
節(jié)流:在一定的時(shí)間內(nèi)只會(huì)請(qǐng)求一次。
可以理解為:公交車,每個(gè)人是一次點(diǎn)擊請(qǐng)求,每十分鐘開一趟車,發(fā)送請(qǐng)求
防抖:觸發(fā)事件后n秒后才能執(zhí)行函數(shù),如果在n秒內(nèi)觸發(fā)了事件,則會(huì)重新計(jì)算執(zhí)行時(shí)間。
比如在一段時(shí)間內(nèi),我一直點(diǎn)擊按鈕,以最后一次點(diǎn)擊為準(zhǔn)發(fā)送一次請(qǐng)求。
節(jié)流實(shí)現(xiàn)
解決思路 :
使用時(shí)間戳(發(fā)生在一段時(shí)間的開始),就是在計(jì)算
當(dāng)前點(diǎn)擊的時(shí)間 - 上一次執(zhí)行函數(shù)的時(shí)間 > 我設(shè)定的時(shí)間戳 ,就執(zhí)行一次函數(shù)
缺點(diǎn):第一次直接觸發(fā) 最后一次一段時(shí)間內(nèi)無法觸發(fā)
給一個(gè)場景,當(dāng)我們搜索數(shù)據(jù)的時(shí)候,發(fā)起請(qǐng)求,沒有做處理是這樣的,請(qǐng)求肯定太過于頻繁
節(jié)流函數(shù)
代碼:
<body> <div> <span>節(jié)流處理</span><input id="input" type="text"> <button id="btn">請(qǐng)求</button> </div> </body> <script> var btn = document.getElementById("btn") btn.addEventListener("click", throttle(output, 1000)) //添加點(diǎn)擊事件監(jiān)聽 function output(e) { console.log(this, e) console.log(document.getElementById("input").value) //模擬發(fā)起一次請(qǐng)求 } //節(jié)流函數(shù) function throttle(fn, delay) { // fn為執(zhí)行的函數(shù),delay為延遲時(shí)間 var last = 0; //上一次結(jié)束的時(shí)間 return function () { var cur = Date.now() console.log(cur-last) if (cur - last > delay) { fn.apply(this, arguments) //執(zhí)行函數(shù) last = cur //更新上一次時(shí)間 } } } </script>
效果:
防抖實(shí)現(xiàn)
解決思路 :
定時(shí)器(發(fā)生在定時(shí)結(jié)束)。缺點(diǎn):第一次不觸發(fā) 最后一次延遲觸發(fā)
就是設(shè)置一個(gè)定時(shí)器,如果一直點(diǎn)擊則清除定時(shí)器,最后一次開啟定時(shí)器
防抖函數(shù)
代碼:
<body> <div> <span>防抖處理</span><input id="input" type="text"> <button id="btn">請(qǐng)求</button> </div> </body> <script> var btn = document.getElementById("btn") btn.addEventListener("click", debounce(output, 1000)) //添加點(diǎn)擊事件監(jiān)聽 function output(e) { console.log(this, e) console.log(document.getElementById("input").value) //模擬發(fā)起一次請(qǐng)求 } function debounce(fn, delay) { // fn為執(zhí)行的函數(shù),delay為延遲時(shí)間 var time = null; //定時(shí)器 return function () { clearTimeout(time); //清除定時(shí)器 let context = this; //獲取當(dāng)前button上下文 如果不指定,箭頭函數(shù)就會(huì)一直往外找到window let args = arguments; time = setTimeout(() => { fn.apply(context, args); }, delay); } } </script>
效果:
防抖升級(jí)版
第一次觸發(fā)和最后一次延遲觸發(fā)
代碼:
function throttle(fn, delay) { // fn為執(zhí)行的函數(shù),delay為延遲時(shí)間 let time = null let flag=true //標(biāo)識(shí)是不是第一次觸發(fā) return function () { clearTimeout(time) if (flag) { fn.apply(this, arguments) flag=false } time = setTimeout(() => { //觸發(fā)定時(shí)器 fn.apply(this, arguments) flag=true }, delay) } }
效果:
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- JavaScript函數(shù)防抖動(dòng)debounce
- 通過實(shí)例講解JS如何防抖動(dòng)
- JavaScript運(yùn)動(dòng)框架 解決防抖動(dòng)問題、懸浮對(duì)聯(lián)(二)
- JavaScript中防抖和節(jié)流的區(qū)別及適用場景
- JavaScript中防抖和節(jié)流的實(shí)戰(zhàn)應(yīng)用記錄
- JavaScript深入理解節(jié)流與防抖
- JavaScript防抖與節(jié)流的實(shí)現(xiàn)與注意事項(xiàng)
- JavaScript的防抖和節(jié)流一起來了解下
- JavaScript中函數(shù)的防抖與節(jié)流詳解
- javascript的防抖和節(jié)流你了解嗎
- 關(guān)于JavaScript防抖與節(jié)流的區(qū)別與實(shí)現(xiàn)
- JavaScript防抖與節(jié)流詳解
- JavaScript 防抖和節(jié)流詳解
- JavaScript防抖動(dòng)與節(jié)流處理
相關(guān)文章
原生JS實(shí)現(xiàn)幾個(gè)常用DOM操作API實(shí)例
下面小編就為大家?guī)硪黄鶭S實(shí)現(xiàn)幾個(gè)常用DOM操作API實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01JavaScript中判斷變量是數(shù)組、函數(shù)或是對(duì)象類型的方法
這篇文章主要介紹了JavaScript中判斷變量是數(shù)組、函數(shù)或是對(duì)象類型的方法,需要的朋友可以參考下2015-02-02js自己實(shí)現(xiàn)一個(gè)大文件切片上傳+斷點(diǎn)續(xù)傳的示例代碼
本文主要介紹了js自己實(shí)現(xiàn)一個(gè)大文件切片上傳+斷點(diǎn)續(xù)傳的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06javascript函數(shù)的call、apply和bind的原理及作用詳解
javascript函數(shù)的call、apply和bind?本質(zhì)是用來實(shí)現(xiàn)繼承的,專業(yè)點(diǎn)說法就是改變函數(shù)體內(nèi)部this的指向,當(dāng)一個(gè)對(duì)象沒有某個(gè)功能時(shí),就可以用這3個(gè)來從有相關(guān)功能的對(duì)象里借用過來,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05淺談Sublime Text 3運(yùn)行JavaScript控制臺(tái)
下面小編就為大家?guī)硪黄獪\談Sublime Text 3運(yùn)行JavaScript控制臺(tái)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06js設(shè)置function參數(shù)默認(rèn)值(適合沒有傳參情況)
div+css模擬js信息框的類庫時(shí)遇到一個(gè)問題當(dāng)沒有傳遞參數(shù)過去時(shí)自動(dòng)使用提示信息作為窗口標(biāo)題,具體的實(shí)現(xiàn)如下2014-02-02