詳細(xì)聊一聊js防抖節(jié)流到底是什么
前言
防抖和節(jié)流,這是前端防止用戶頻繁調(diào)用同一個(gè)接口的方法,比如短時(shí)間重復(fù)點(diǎn)擊上傳同一個(gè)文件,短時(shí)間重復(fù)點(diǎn)擊提交同一個(gè)評(píng)論,異步的操作還沒(méi)給你帶來(lái)反饋,于是你重復(fù)上傳了多個(gè)文件,重復(fù)提交了多個(gè)評(píng)論。
本文以常見(jiàn)的使用場(chǎng)景與解決方案,一篇教會(huì)你如何使用防抖節(jié)流。
場(chǎng)景
為了例子更加簡(jiǎn)單,我們就用延遲來(lái)模擬一個(gè)后端接口返回的過(guò)程。
<body> <button onclick="comment()">發(fā)表評(píng)論</button> <script> const commentApi = () => { // 我們使用延遲模擬異步請(qǐng)求 setTimeout(() => { const div = document.createElement('div') div.innerText = '本人到此一游' document.body.appendChild(div) }, 1000) } const comment = () => { // 請(qǐng)求發(fā)布評(píng)論Api commentApi() } </script> </body>
以上是一個(gè)發(fā)表評(píng)論的例子,由于接口一秒后才會(huì)響應(yīng)評(píng)論反饋到界面上。
用戶本意只是發(fā)布一條評(píng)論,但是由于接口需要響應(yīng)時(shí)間,他以為自己的第一次點(diǎn)擊沒(méi)有生效于是就多點(diǎn)擊了兩次,結(jié)果顯而易見(jiàn),就是非用戶本意的發(fā)布了三條一樣的評(píng)論。
我們希望的是用戶不要在請(qǐng)求還在進(jìn)行的時(shí)候,頻繁的重復(fù)發(fā)送請(qǐng)求。這時(shí)候就需要防抖節(jié)流了。
防抖
核心
- 設(shè)置延遲,短時(shí)間高頻率觸發(fā)只有最后一次觸發(fā)成功
解釋
防抖指的是設(shè)置延時(shí)器,比方說(shuō)我點(diǎn)擊之后設(shè)置一個(gè)1s的延遲,1s后開(kāi)始上傳。
如果在1s之中再次點(diǎn)擊該事件,那么這個(gè)延遲被清除,重置1s的延遲,也就是還沒(méi)開(kāi)始上傳你得重新等待1s。
也就是無(wú)論你如何一直亂點(diǎn),也只有你停止點(diǎn)擊后的最后一次點(diǎn)擊會(huì)成功。
修復(fù)場(chǎng)景例子
快速點(diǎn)擊幾次,還是只會(huì)發(fā)送一條評(píng)論。
但是缺點(diǎn)就是用戶得到響應(yīng)的時(shí)間更久了,得要算上延遲加上接口的響應(yīng)。
<body> <button onclick="comment()">發(fā)表評(píng)論</button> <script> const commentApi = () => { // 我們使用延遲模擬異步請(qǐng)求 setTimeout(() => { const div = document.createElement('div') div.innerText = '本人到此一游' document.body.appendChild(div) }, 1000) } let later const comment = () => { // 如果已經(jīng)設(shè)置過(guò)延遲請(qǐng)求,則重置延遲 if (later) { clearTimeout(later) } later = setTimeout(() => { commentApi() }, 1000) } </script>
所以防抖一般也不完全適合此類型的場(chǎng)景,它更適合需要一定操作結(jié)束之后再執(zhí)行的場(chǎng)景,比如請(qǐng)你輸入一段話,輸入結(jié)束之后再進(jìn)行請(qǐng)求,當(dāng)然不希望你在輸入的過(guò)程中就開(kāi)始請(qǐng)求了,于是設(shè)置防抖,直到發(fā)覺(jué)你停止輸入了才開(kāi)始請(qǐng)求。
節(jié)流
核心
- 設(shè)置狀態(tài)鎖,短時(shí)間高頻率觸發(fā)只有第一次會(huì)觸發(fā)成功
解釋
節(jié)流是設(shè)置狀態(tài)鎖,比如設(shè)置一個(gè)key作為鎖,鎖一開(kāi)始的狀態(tài)是關(guān)閉的,我們將key設(shè)置為false。
當(dāng)你點(diǎn)擊的時(shí)候,會(huì)對(duì)key進(jìn)行判斷,如果發(fā)現(xiàn)key為false,未上鎖,那么開(kāi)始請(qǐng)求,并且與此同時(shí)給key上鎖,將flag設(shè)置為true。
然后這時(shí)候你繼續(xù)點(diǎn)擊請(qǐng)求的時(shí)候,同樣要判斷key,發(fā)現(xiàn)上鎖了,你怎么點(diǎn)擊也沒(méi)用。
然后什么時(shí)候再將鎖關(guān)閉呢?在你接口返回給前端,提示你已經(jīng)上傳完畢了之后,再將key關(guān)閉置為false,就可以再次提交請(qǐng)求了。
修復(fù)場(chǎng)景例子
快速點(diǎn)擊幾次,還是只會(huì)發(fā)送一條評(píng)論。只有一條請(qǐng)求發(fā)布成功之后,才能夠發(fā)布第二條請(qǐng)求,對(duì)于該場(chǎng)景十分合適。
<body> <button onclick="comment()">發(fā)表評(píng)論</button> <script> let key = false const commentApi = () => { setTimeout(() => { const div = document.createElement('div') div.innerText = '本人到此一游' document.body.appendChild(div) // 請(qǐng)求結(jié)束,解鎖 key=false }, 1000) } const comment = () => { // 未上鎖開(kāi)始執(zhí)行 if (!key) { // 請(qǐng)求開(kāi)始,上鎖 key = true commentApi() } } </script> </body>
總結(jié)
函數(shù)防抖:將多次操作合并為一次操作進(jìn)行。原理是維護(hù)一個(gè)計(jì)時(shí)器,規(guī)定在delay時(shí)間后觸發(fā)函數(shù),但是在delay時(shí)間內(nèi)再次觸發(fā)的話,就會(huì)取消之前的計(jì)時(shí)器而重新設(shè)置。這樣一來(lái),只有最后一次操作能被觸發(fā)。
函數(shù)節(jié)流:使得一定時(shí)間內(nèi)只觸發(fā)一次函數(shù)。原理是通過(guò)判斷是否有延遲調(diào)用函數(shù)未執(zhí)行。
區(qū)別: 函數(shù)節(jié)流不管事件觸發(fā)有多頻繁,都會(huì)保證在規(guī)定時(shí)間內(nèi)一定會(huì)執(zhí)行一次真正的事件處理函數(shù),而函數(shù)防抖只是在最后一次事件后才觸發(fā)一次函數(shù)。 比如在頁(yè)面的無(wú)限加載場(chǎng)景下,我們需要用戶在滾動(dòng)頁(yè)面時(shí),每隔一段時(shí)間發(fā)一次 Ajax 請(qǐng)求,而不是在用戶停下滾動(dòng)頁(yè)面操作時(shí)才去請(qǐng)求數(shù)據(jù)。這樣的場(chǎng)景,就適合用節(jié)流技術(shù)來(lái)實(shí)現(xiàn)。
到此這篇關(guān)于js防抖節(jié)流到底是什么的文章就介紹到這了,更多相關(guān)js防抖節(jié)流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 利用JavaScript實(shí)現(xiàn)防抖節(jié)流函數(shù)的示例代碼
- JavaScript函數(shù)防抖與函數(shù)節(jié)流的定義及使用詳解
- JS中節(jié)流和防抖函數(shù)的實(shí)現(xiàn)及區(qū)別示例
- JavaScript防抖動(dòng)與節(jié)流處理
- JavaScript中防抖和節(jié)流的區(qū)別及適用場(chǎng)景
- JavaScript防抖與節(jié)流的實(shí)現(xiàn)與注意事項(xiàng)
- JavaScript的防抖和節(jié)流一起來(lái)了解下
- JavaScript中函數(shù)的防抖與節(jié)流詳解
- JavaScript防抖與節(jié)流超詳細(xì)全面講解
相關(guān)文章
Javascript農(nóng)歷與公歷相互轉(zhuǎn)換的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇Javascript農(nóng)歷與公歷相互轉(zhuǎn)換的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10js setTimeout()函數(shù)介紹及應(yīng)用以倒計(jì)時(shí)為例
setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式,下面有個(gè)倒計(jì)時(shí)的示例,需要的朋友可以學(xué)習(xí)下2013-12-122019 年編寫(xiě)現(xiàn)代 JavaScript 代碼的5個(gè)小技巧(小結(jié))
這篇文章主要介紹了2019 年編寫(xiě)現(xiàn)代 JavaScript 代碼的5個(gè)小技巧,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01javascript string字符串優(yōu)化問(wèn)題
今天看到一個(gè)很久的帖子說(shuō)string連接優(yōu)化問(wèn)題。于是自己也測(cè)試一下。寫(xiě)了個(gè)很簡(jiǎn)單的代碼2011-07-07JavaScript實(shí)現(xiàn)緩動(dòng)動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)緩動(dòng)動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11JS+JSP checkBox 全選具體實(shí)現(xiàn)
本文為大家介紹下使用JS+JSP實(shí)現(xiàn)checkBox全選,下面有個(gè)不錯(cuò)的示例,感興趣的朋友可以參考下2014-01-01一文詳解如何使npm-scripts更好維護(hù)的配置方法
這篇文章主要為大家介紹了如何使npm-scripts更好維護(hù)的配置方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06JavaScript實(shí)現(xiàn)計(jì)數(shù)器基礎(chǔ)方法
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)計(jì)數(shù)器的基礎(chǔ)方法2017-10-10
,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下