問題由來:html
在項目應用PeoplePicker控件的時候忽然聯想到一個問題,在輸入人名時不停的向後臺發請求,取到數據庫裏面的數據。咱們都知道頻繁的通訊會致使頁面效率下降。可不能夠設置個間隔,每次這個間隔通訊一次而不是每次輸入一個字符就通訊一次呢。其實這裏還有不少場景,好比resize事件,scroll事件。都會讓一個回調函數不停的執行。頁面操做成本是很是高的,若是不停的執行頁面效率會打打折損。因而產生了兩種解決方案:函數節流、函數去抖。數據庫
函數節流:閉包
頻繁的調用一個函數,咱們能夠添加一些限制,能夠緩解頻繁調用,咱們能夠設置個時間間隔,每次到時間調用一次。app
代碼:dom
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body> <input id="search" type="text" name="search"> <script> function queryData(text) { console.log(text); } var input = document.getElementById("search"); var handler = throttle(queryData, 1000); input.addEventListener("keyup", function (event) { handler(this.value); }); function throttle(fn, delay) { var self = this, lastTime = 0, timer; return function (value) { var now = new Date().getTime(); if (now - lastTime <= delay) { return; } lastTime = now; clearTimeout(timer); timer = setTimeout(function () { timeout = null; fn.apply(self, [value]); }, delay) } } </script> </body> </html>
思路:利用閉包函數throttle保存timer以及lastTime,若是兩次的調用時間間隔小於設置的規定時間,就不去調用目標函數,若是大於這個時間間隔,就去設置一個timer,而後執行這個函數。這樣作的目的能夠達到頻繁調用函數,可是須要在一段時間纔回去執行該函數,這種方式就叫作函數節流。函數
效果:優化
一直不停的輸入,沒1秒會打一次log。this
函數去抖:spa
去抖能夠理解成爲是節流的一種狀況,在一個條件內函數一直不執行,直到調出該條件。code
代碼:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body> <input id="search" type="text" name="search"> <script> function queryData(text) { console.log(text); } var input = document.getElementById("search"); var handler = debounce(queryData, 5000); input.addEventListener("keyup", function (event) { handler(this.value); }); function debounce(fn, delay) { var timer, self = this; return function (value) { clearTimeout(timer); timer = setTimeout(function () { timer = null; fn.apply(self, [value]); }, delay); }; } </script> </body> </html>
思路:函數調用n秒後纔會執行,若是函數在n秒內被調用的話,則函數不執行,從新計算執行時間。
效果:
不停的輸入不會打出log,中止輸入打出log。
總結:函數節流在必定程度上能夠優化頁面效率,減小不必的dom渲染以及http請求,更重要的是對js能夠有一個更深刻的理解。