JavaScript - Throttle (節流) 常見的面試問題 (Scrollbar, Infinite Scroll) (前端優化)
Summary
TLDRThe video script introduces the concept of Throttling, a technique similar to Debouncing but with distinct behaviors. It demonstrates how Throttle can be applied to implement an Infinite Scroll feature on a webpage. The script provides a step-by-step guide on creating a Throttle function, emphasizing the importance of using a regular function for the callback to avoid arrow function scoping issues. It also explains the difference between Throttle, which executes the callback at regular intervals during an action, and Debounce, which executes the callback after the action has ceased for a specified time.
Takeaways
- 🚦 Throttle and Debounce are similar concepts but have distinct differences in their execution. Throttle is used for controlling the frequency of function execution, while Debounce is for delaying the execution until a certain amount of time has passed without any further triggering.
- 🔄 The Throttle function is implemented with two parameters: the callback function to be executed and the time interval.
- 🔧 In the Throttle function, a timer is used to control the frequency of execution, and it's shared across all invocations of the function through closure.
- ⏱️ The Throttle function should clear the timer before executing the callback to ensure it doesn't accumulate multiple timers.
- 🎯 Throttle is used to solve scenarios where you want a function to fire at a consistent interval while an action is being performed, like loading new elements on scroll.
- 📈 The Infinite Scroll functionality can be achieved by using Throttle to check scroll position and load more content when nearing the end of the list.
- 📊 To determine if the scroll has reached the bottom, the script calculates the sum of scroll position and client height, and compares it to the scroll height.
- 🤔 Floating-point arithmetic issues can cause the scroll position check to be inaccurate, so adding a buffer (like 10 pixels) to the comparison can ensure more reliable results.
- 🔄 The video script suggests that for early loading of content, the check can be triggered at a certain percentage (e.g., 90%) of the scroll height.
- 👷 The use of a regular function (not an arrow function) in Throttle allows for the preservation of the function context, which is important if the callback function expects to have access to specific arguments or the 'this' keyword.
- 🔗 If the callback function requires arguments or a specific 'this' context, the Throttle function should return a version of the callback that has been bound with the correct context and arguments using methods like 'apply'.
Q & A
What is the main topic of the video?
-The main topic of the video is the implementation of the Throttle function in JavaScript, which is used to control the rate at which a function is executed. The context of its use in creating an infinite scroll feature is also discussed.
How does Throttle differ from Debounce, according to the video?
-Throttle differs from Debounce in that Throttle controls the execution rate of a function during continuous actions, executing the function at regular intervals, while Debounce waits for the action to stop and then executes the function after a certain delay.
Why does the presenter decide not to use an arrow function for the Throttle implementation?
-The presenter decides not to use an arrow function for the Throttle implementation because the context of 'this' and the passing of arguments are not concerns for the example shown. However, for situations where 'this' binding or argument passing is necessary, a different approach would be required.
What problem does Throttle solve in the video demo?
-In the video demo, Throttle solves the problem of excessive function executions during continuous events, such as scrolling. It's applied to efficiently load new elements for an infinite scroll feature without overwhelming the browser with too many calls.
What kind of elements are initially created on the webpage for the infinite scroll demo?
-For the infinite scroll demo, the webpage initially creates 30 paragraph ('p') tags to enable scrolling and demonstrate the functionality.
What criteria are used to load more elements in the infinite scroll feature?
-More elements are loaded in the infinite scroll feature when the scrollbar reaches the bottom of the page. This is determined by calculating if the sum of scrollTop and clientHeight equals the scrollHeight, indicating that the bottom has been reached.
What adjustments are made to handle floating point issues when checking if the bottom of the page is reached?
-To handle floating point issues when checking if the bottom of the page is reached, a small additional value (like 10) might be added to the sum of scrollTop and clientHeight to ensure it exceeds scrollHeight, accommodating any discrepancies due to floating point calculations.
How is the Throttle function adjusted to handle parameters and 'this' binding if needed?
-If parameters and 'this' binding are needed, the Throttle function can be adjusted by using 'apply' to bind 'this' and pass arguments to the callback function, ensuring the correct context and parameters are used during execution.
What suggestion from a viewer does the presenter mention at the beginning?
-The presenter mentions a suggestion from a viewer regarding a problem that could be solved using the Throttle function, highlighting the practical application of concepts discussed in the video.
What alternative threshold is suggested for triggering the loading of new elements before reaching the bottom of the page?
-An alternative threshold suggested is checking if the ratio of (scrollTop + clientHeight) to scrollHeight is greater than or equal to 0.9, indicating the scrollbar is 90% down the page, which triggers loading new elements before actually reaching the bottom.
Outlines
🚦 Introduction to Throttling and Infinite Scroll
The video begins with an introduction to the concept of throttling, drawing parallels to the previously discussed debounce technique. The main focus is on demonstrating how to implement an Infinite Scroll feature using throttling. The speaker explains that the Throttle function will be triggered by the scrolling action and will execute a callback function at specified intervals. A practical example is given, where the Throttle function is used to load new elements into the page as the user scrolls towards the bottom. The setup includes creating 30 placeholder elements to enable scrolling and defining the Throttle function with a 1-second delay. The explanation delves into the technical details, emphasizing the difference between throttle and debounce, and highlighting the importance of using a regular function instead of an arrow function for scope reasons.
📏 Cross-Browser Scrollbar Handling and Throttling Logic
This paragraph delves into the specifics of handling the scrollbar across different browsers and the logic behind the throttling mechanism. The speaker discusses the importance of using `documentElement.clientHeight` for cross-browser compatibility and introduces the calculation for determining when the user has reached the bottom of the page. The concept of floating-point precision is addressed, and a solution is offered by adding a buffer value to the comparison. The speaker then demonstrates how to load more elements into the page when near the bottom, enhancing the Infinite Scroll experience. The explanation includes writing a loop to create new paragraph tags and appending them to the DOM, as well as adjusting the throttling function to accommodate for early loading at 90% of the scroll position.
🔄 Throttle vs Debounce and Function Binding
The speaker concludes the video by contrasting the Throttle function with the Debounce function. While Debounce waits for an action to stop before executing the callback function, Throttle executes the callback at regular intervals as long as the action is being performed. The speaker reiterates the key difference and provides a final overview of the Throttle function's implementation. Additionally, the importance of using regular functions for callbacks that do not require arguments or `this` binding is emphasized. The speaker also touches on how to adjust the Throttle function for callbacks that do require arguments or `this` binding, suggesting the use of `apply` for context and arguments passing.
Mindmap
Keywords
💡Throttle
💡Debounce
💡Infinite Scroll
💡Callback Function
💡Timer Variable
💡SetTimeout
💡Event Listener
💡Scroll Event
💡Document Object Model (DOM)
💡Closure
Highlights
Introduction to Throttle and its similarity to Debounce
Throttle function implementation and its difference from Debounce
Use case demonstration of Throttle with a scrolling element
Explanation of Throttle function parameters: callback and time
Avoiding the use of arrow functions for Throttle function
Utilizing closure to share the timer variable among Throttle calls
Setting up a timer with setTimeout within Throttle function
Clearing the timer to prevent accumulation of timeouts
Difference in behavior between Throttle and Debounce
Implementation of Infinite Scroll using Throttle
Adding 30 p tags to the page for scrolling demonstration
JavaScript code for Throttle function with detailed explanation
Handling of scroll event listener with Throttle
Checking if the scrollbar has reached the bottom
Loading new elements when reaching the end of the scroll
Adjusting the threshold for triggering new content load
Addressing the callback's arguments and context (this) binding
Conclusion summarizing the key differences between Throttle and Debounce
Transcripts
那我們今天來介紹的是 Throttle
就是節流
那如果有看過我上一支影片在講 Debounce 的話
你會發現說它其實和 Debounce 蠻像的
當然有一些不同的地方
等我們把 Throttle function 實作完再來簡單的講一下
它跟 Debounce 有什麼不一樣
今天要 Demo 的畫面會長這樣子
昨天有一位觀眾跟我問問題
那剛好他問的問題就可以直接用 Throttle 來解決
我們就直接來看一下
目前我畫面上有一些元素
有一些文字在上面
注意到我右邊的 Scrollbar 它目前的長度是這樣子
其實現在這樣滑 在我去滾動我的 Scrollbar 的時候就已經觸發 Throttle 了
我寫的判斷是說
如果我的滾動軸已經滑到底部的話
就去幫我加載 去載入新的元素進來
這跟我們之前用 Observer API 做的方式很像
你看我一直往下滾
它就一直幫我長新的元素出來
大概是這樣子
那我們知道我們現在要做出 Infinite Scroll 的話 就直接開始
那現在畫面上是沒有任何東西的
那如果要實做 Infinite Scroll 的話 當然要有一些東西在畫面上
所以我先簡單的長出 30 個 p 標籤
這樣子就可以滾動了
OK 沒有問題
那接著就來到 JavaScript 的部分
那我就直接去實作我的 Throttle 的 function
好 那跟 Debounce 一樣 它一樣會有兩個參數需要丟進去
第一個就是我們要執行的 function
所以我叫它 callback
第二個是延遲的時間叫做 time 那設定為 1 秒
就是 1000ms
這裡面了一樣 我們回傳一個 function
那這邊要注意到的是 我這邊不使用 arrow function
我這邊不使用 arrow function 那原因是什麼我等下會解釋一下
就用正常的 function
在裡面呢
一樣 我們要先在一開始進來 Throttle function 的時候要有一個 timer 變數
使用閉包讓使用 Throttle function 的可以去共享這個 timer 變數
然後在裡面一樣 就去實作我的 setTimeout 就好了
延遲時間是 1 秒
在 setTimeout 裡面除了要去執行 callback 以外
我們還要去把 timer 給清空
那就直接把它設定為 null 就好了
那會這樣做的原因是因為 它跟 Debounce 不一樣的地方在於
如果我現在在滾動我的滾動軸的話
那我現在執行麻 所以他應該要知道
那就根據我設定給它的延遲時間 每隔 1 秒
就去執行我 callback 裡面的內容
每隔 1 秒就去執行我 callback 裡面的內容
所以它跟 Debounce 不一樣
Debounce 是在說我們停下來以後
它才去執行我 callback 裡面的內容
但 Throttle 節流就是說你目前有做這個動作嗎?
有 那我就根據你給我的時間
每隔幾秒要執行一次 我就去幫你執行
但是我們現在寫成這樣子 還會有一個問題
就是說如果我們已經有一個 timeout
已經有一個計時器在跑了
那如果我們又滾動我們的滾動軸的話
那它是不是累積這個 累加這個 timeout 下去
但這並不是我們要結果
所以我們還要在這邊去做個判斷
判斷說
我的這個 timer 目前有沒有值
好 如果有的話你就幫我 return 就好了 什麼事都不用幫我做
那如果沒有的話 它就會去跑下面這一行程式碼
去設定給它一個 timeout
好那就先這樣子 其實這樣寫完就是一個 Throttle 的 function 了
所以我們現在要去寫的是 Infinite Scroll 的邏輯
所以我們的 Throttle function 已經寫完了喔
那但是等下還會有一些
參數傳遞的問題
我到最後再來講一下
那我先 console.log 確定一下有沒有問題
那我在我的
document 去設定一個監聽器
當我的滾動軸滾動的時候 去觸發這個 event
那這邊我就可以直接去使用 Throttle function 了
那裡面我們就只需要傳遞一個參數進去
就是我們的 callback
就直接把我們的 scroll function 丟進去
那第二個參數我可以填或是不填都可以
如果我要去填寫它延遲執行的時間 就可以在第二個參數去傳遞
但這邊就不用了 就讓它延遲 1 秒執行就好了
那這邊我先測試一下 我先儲存
然後重新整理一下
然後我現在去滾動一下我的滾動軸
你就會發現說 我目前只要滾動我的滾動軸的話 它每隔 1 秒
就會在我的 console
印出 scroll
也就是我們要的效果了
我們已經達到所謂的延遲執行了
那下一個步驟就是要去判斷說
我們這個 Scrollbar 是不是已經到底部了
如果是的話 我們就去加載 去載入更多的元素到我們的畫面
所以我這邊去 很簡單的寫一下這個邏輯
去取得 client 的 height
那這邊可能會根據不同的瀏覽器有不同的寫法
那我記得 因為我之前好像寫 document.body
然後 .clientHeight 的話 它好像取得不到東西
我只能寫這個 documentElement
所以如果你要跨瀏覽器的話
你就需要寫成這樣子
document.body.clientHeight
這個比較確保比較保險一點的寫法如果你不確定
你這個功能在其他瀏覽器能不能運作的話 就寫成這樣子
但是我這邊先簡寫成前面這樣就好了
就直接去取得 documentElement 裡面的 clientHeight
那再來是我要去取得 scrollTop
那這邊可以做一個簡單的運算
它固定的公式是這樣子的
假設我們的 scrollTop 加上我們的 clientHeight
如果等於 scrollHeight 的話
代表它已經到底部了
但這樣寫其實會有一個問題 我們先來看一下會不會有這個問題出現
所以這邊先把它 console 出來
把我的 scrollTop 加 clientHeight
這個數值加起來後 顯示在 console
然後還有我們的 scrollHeight
現在往下滑動 你會看到說它已經再執行運算了
但你會發現說 有這個小數點 浮點數的這個問題
所以要是我滑到底部的話
他有可能不會等於
可能會差 1 或是少 1 都有可能
所以比較確保的做法
通常可能會在這邊再去加一點數值
判斷一下這些數值運算完之後加10
是不是大於我的 scrollHeight
就不要把它判斷說 完全等於
所以現在這樣寫完之後再重新整理一下 然後滑到最底部
你會看到說 我的這個 bottom 文字出現了
這是進到 if 裡面才會有這個文字出現
所以我們現在可以在裡面去判斷說
我們現在可以在裡面知道說 它已經滑到底部了 所以去載入更多元素進來
那載入更多元素這件事情蠻簡單的 我們寫一個 for 迴圈
我們去建立一個 新的 p 標籤
然後這個 p 標籤就隨便給一個文字
最後就我的 result 我的 result 在這邊
在這塊裡面
就直接用 appendChild
新建立出來的這個 node
p 標籤 node 直接丟進去
所以如果我現在執行下來的話
知道我到底部之後 就會直接渲染新的 p 標籤出來 在我的這個畫面上
所以這個 Infinite Scroll 已經完成了 我們來看一下喔
先滑到最上面 儲存一下
只要滑到底部
就會一直載入新的元素出來
那如果你想要提前 不想要滑到底部才去載入的話
如果想要提前的話 可以使用另外一個算法 這邊去改一下判斷
去判斷說我們的 scrollTop
加上 clientHeight
除與我們的 scrollHeight
是不是大於等於0.9
1 就是底部的意思 (100%) 那 0.9 就是 90% 的位置
一樣可以儲存一下
慢慢滑下去
我現在沒有滑到底 但是我慢慢的滑 滑到大概 90% 的位置
就會去載入我新的元素出來了
所以如果你不想讓它到底部才去執行這件事情的話
你就可以這樣子去判斷
那 Throttle 的話就是這樣子 那我最後再講一個
就是說 我們剛剛前面有講到
我們的這個 function 是使用一般 function 不是 arrow function
那是因為我的 callback
它沒有參數的傳遞 也沒有 this 的問題 所以我才敢這樣寫
那如果今天
你的這個 callback 裡面可能有牽扯到 args 或是 this 的問題
你就需要在這個 return 裡面去做一個綁定 this
就把它寫成一個變數在外面去綁定
然後在 timeout 裡面丟進去
所以現在這邊也不能這樣寫了 如果你要做 this 的綁定和參數的傳遞的話
就要用 apply
然後第一個就要丟 context 進去 然後是我的 args
其實這樣執行起來是沒有差 以我這個例子來說是沒有差的
因為我沒有參數的傳遞 那如果你今天有參數的傳遞又要綁定 this 的話
就要這樣去寫
那針對 Throttle 的介紹應該就到這邊了
也非常感謝那一位觀眾給我的建議
好那我們可以知道說
跟 Debounce 的比較就我們前面有講過一遍了嘛
Debounce 是當我動作停下來
等幾秒後沒有再繼續執行的時候
它才去幫我執行我的 callback
就是說我 function 裡面的內容
Throttle 不一樣的地方就是說 我現在有在執行這個動作 那你每隔幾秒就要幫我執行 callback 裡面的內容
Browse More Related Video
The bind Method | JavaScript 🔥 | Lecture 125
More Closure Examples | JavaScript 🔥 | Lecture 129
Komposisi Fungsi - Matematika Wajib Kelas XI Kurikulum Merdeka
useEffect to the Rescue | Lecture 140 | React.JS 🔥
RxJS Top Ten - Code This, Not That
Evaluating composite functions | Mathematics III | High School Math | Khan Academy
5.0 / 5 (0 votes)