让你彻底了解什么是节流
題圖 By HymChu From lnstagram
上一篇文章咱們介紹了防抖,這一篇文章大咱們討論一下節(jié)流,同樣咱們看一個(gè)需求:頁(yè)面中有一個(gè)文本框,文本框根據(jù)用戶的輸入,發(fā)送異步請(qǐng)求關(guān)聯(lián)數(shù)據(jù),顯示在輸入框下面。
初步實(shí)現(xiàn)代碼如下:
<!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" content="ie=edge"><title>Document</title></head><body><input type="text" name="" id="inp"><script>document.querySelector("#inp").oninput = function(){console.log("22222")}</script></body></html>
不考慮性能的話,功能完全能實(shí)現(xiàn),但是我們看一下控制臺(tái),input只要一有輸入,就會(huì)調(diào)用事件函數(shù),我們發(fā)現(xiàn)這是不必要的,有的朋友可能想到了上一篇文章的防抖,用防抖也可以實(shí)現(xiàn)這個(gè)功能,但是用防抖的話有一個(gè)小問(wèn)題,那就是等用戶完全輸入停止后才去發(fā)送異步請(qǐng)求。
但是我們需要用戶輸入時(shí)候到某個(gè)時(shí)間節(jié)點(diǎn),不論用戶有沒(méi)有輸入完成都發(fā)送一次異步請(qǐng)求,用戶持續(xù)的輸入,持續(xù)的觸發(fā)input事件,只要到達(dá)某事時(shí)間間隔,就發(fā)送一次ajax。這樣操作會(huì)提升用戶體驗(yàn)。
按照上面的描述,咱們來(lái)思考一下如何實(shí)現(xiàn)上面的代碼,首先應(yīng)該有一個(gè)全局變量來(lái)獲取當(dāng)前的時(shí)間starttime,然后觸發(fā)input事件的時(shí)候,獲取觸發(fā)事件的當(dāng)前時(shí)間currenttime,然后對(duì)比兩個(gè)時(shí)間的時(shí)間差,如果插值大于等于規(guī)定的時(shí)間間隔timespace,發(fā)送ajax,并且更新starttime,如果小于時(shí)間間隔timesapce,不做處理,代碼流程圖如下:
按照流程圖,代碼實(shí)現(xiàn)如下:
<script>var starttime = Date.now();var currenttime = null;var timespace = 3000function ajax(){console.log("異步請(qǐng)求,渲染dom")}document.querySelector("#inp").oninput = function(){currenttime = Date.now();if(currenttime-starttime>timespace){ajax()starttime = Date.now();}else{console.log("不做處理")}}</script>
仔細(xì)閱讀代碼,發(fā)現(xiàn)代碼又bug,當(dāng)用戶完全輸入后,反而不會(huì)觸發(fā)ajax。所以我們要進(jìn)行處理,添加一個(gè)判斷,判斷用戶輸入完成后,觸發(fā)ajax請(qǐng)求,代碼修改如下:
<script>var starttime = Date.now();var currenttime = null;var timespace = 3000// 添加延時(shí)器全局變量var timeout = null;function ajax(){console.log("異步請(qǐng)求,渲染dom")}document.querySelector("#inp").oninput = function(){currenttime = Date.now();if(currenttime-starttime>timespace){clearTimeout(timeout);starttime = Date.now();timeout = null;ajax()}else{// 判斷有無(wú)定時(shí)器if(!timeout){// 沒(méi)有定時(shí)器的話,打開(kāi)定時(shí)器timeout = setTimeout(function(){ajax();// 調(diào)用完成后將timeout清空timeout = null;},4000)}}}</script>
這次基本實(shí)現(xiàn)了節(jié)流的應(yīng)用,我們看到節(jié)流一般和防抖結(jié)合使用,因?yàn)楣?jié)流的最后要判斷用戶是否輸入完成。
上面的代碼依然有好多問(wèn)題,暴露了多個(gè)全局變量,不能復(fù)用,更改代碼如下:
<script>function ajax(){console.log("異步請(qǐng)求,渲染dom")}?function throttle(callback){var starttime = Date.now();var currenttime = null;var timespace = 3000var timeout = null;return function(){// 用context和event保存調(diào)用事件的this和事件對(duì)象var context = this;var event = arguments[0]currenttime = Date.now();if(currenttime-starttime>timespace){clearTimeout(timeout);starttime = Date.now();timeout = null;// 使callback綁定事件調(diào)用對(duì)象,和事件對(duì)象callback.call(context,event)}else{// 判斷有無(wú)定時(shí)器if(!timeout){// 沒(méi)有定時(shí)器的話,打開(kāi)定時(shí)器timeout = setTimeout(function(){// 使callback綁定事件調(diào)用對(duì)象,和事件對(duì)象callback.call(context,event)// 調(diào)用完成后將timeout清空timeout = null;},4000)}}}}??document.querySelector("#inp").oninput = throttle(ajax)</script>
我們實(shí)現(xiàn)了throttle函數(shù),這個(gè)函數(shù)可以將事件的主要邏輯函數(shù)變?yōu)橐粋€(gè)節(jié)流函數(shù),并且我們根據(jù)throttle返回的函數(shù)最終調(diào)用者為inputDom,所以用變量context和event保存調(diào)用事件邏輯的this和事件對(duì)象,然后將其綁定到callback上面。
針對(duì)上面的過(guò)程,我們給節(jié)流下一個(gè)定義:事件一直觸發(fā),我們獲取事件觸發(fā)時(shí)間,比較兩次觸發(fā)時(shí)間的間隔,當(dāng)這個(gè)時(shí)間間隔達(dá)到某個(gè)閥值的時(shí)候,觸發(fā)事件處理邏輯。
關(guān)聯(lián)文章:白話防抖。
以上便是節(jié)流的簡(jiǎn)單實(shí)現(xiàn),如果你有什么建議或者想法歡迎留言。
歡迎轉(zhuǎn)發(fā)、關(guān)注、點(diǎn)擊好看
堅(jiān)持下去就能成功
總結(jié)
以上是生活随笔為你收集整理的让你彻底了解什么是节流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 理财风险评估即将失效是什么意思?
- 下一篇: 理财被骗法院一直不审怎么办?