前言
2020 秋天,我將用 30 天的時間,來嘗試回答和網路前端開發相關的 30 個問題。30 天無法一網打盡浩瀚的前端知識,有些問題可能對有些讀者來說相對簡單,不過期待這趟旅程,能幫助自己、也幫助讀者打開不同的知識大門。有興趣的話,跟著我一起探索吧!
Debounce 和 Throttling 是兩個開發上的技巧,常在前端開發的場景出現,不過當然也是應用在後端當中。這裡兩個技巧的目的都是要「降低對高頻 events 的反應」。
「降低對高頻 events 的反應」這句話可能有點難懂,舉例來說,假設我們透過 DOM 在頁面上的某個按鈕裝上 EventListener 並監聽 click event,每當使用者點擊之後,就會透過 API 向 server 發出請求。
然而如果使用者高速、連續點擊按鈕,那麼在短時間內,就會送出很多次同樣的請求,雖然使用者只需要一次來自 server 的回應而已。
當然我想不管是多厲害的使用者手速,可能對 server 來說都是小 case,但如果今天送出請求的是機器人,或者我們監聽的是像 scroll
這種本身就會產生高頻 events 的動作,那麼就需要針對高頻 events 做處理。
以下就分別介紹 debounce 和 throttling 兩種技巧
debounce 的概念是,會將連續出現的請求,整合成一個請求,請求的時間點,取決於我們的設定。
譬如以下面這個例子來說,我們會在一段連續出現的 events 結束之後一段時間,才會發出 function call
而在下面這個例子,則是在最一開始就發出請求,但是之後連續出現的 events,就不會再發出新的請求
看到這裡,可能會想到一個問題:我們是怎麼判斷「連續」這件事情。因此在實作 debounce 的時候,會設定一個延遲時間區間,如果兩次 events 出現的時間小於這個時間區間,那麼就會被判定成「連續」。
throttling 的概念是限流,也就是在一定的時間區間內,只讓限定數量的 events 通過,實際上就是「在一定的時間區間內,只會發出一次請求」。
以下圖的例子來說,在一段很長的、連續的 events 當中,每隔一段時間才會固定發出一次請求。
在 JavaScript 的實作上,可以透過 setTimeout 來達到延遲效果,有興趣的話可以參考網路上許多人的作法,譬如[這篇文章](Debouncing and Throttling in JavaScript)。
不過實際上,我們可以透過 lodash 或是 underscore 來快速實作出 debounce 或 throttling,就不需要重複製造輪子了。
Debounce 和 Throttling 兩個技巧所要處理的效能問題,其實在開發的過程中隨處可見,只是嚴重的程度不同而已。處處留心,就能夠找到讓應用程式變得更好的機會!