JavaScript - Throttle (節流) 常見的面試問題 (Scrollbar, Infinite Scroll) (前端優化)

Wei Wei
17 Feb 202310:41

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

00:00

🚦 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.

05:02

📏 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.

10:05

🔄 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

Throttle, in the context of this video, refers to a programming technique used to limit the rate at which a function can be executed. This is particularly useful in situations where certain code shouldn't run too frequently, such as handling scroll or resize events. The presenter uses Throttle to solve a viewer's question by applying it to an infinite scroll functionality, demonstrating how Throttle prevents excessive function calls by only executing at every fixed time interval (e.g., every second) as the user scrolls.

💡Debounce

Debounce is another programming technique that ensures a function is executed after the caller stops calling it for a certain period. It's similar to Throttle but with a key difference: Debounce waits for the event to stop firing for a predefined time before executing the function, making it ideal for situations like search input fields where you don't want to execute the search query for every keystroke. In the video, the presenter compares Debounce to Throttle, highlighting that while both manage the rate of function execution, they do so in different ways.

💡Infinite Scroll

Infinite Scroll is a web design technique that loads content continuously as the user scrolls down the page, eliminating the need for pagination. The presenter uses Throttle to implement infinite scroll by loading new elements whenever the scrollbar reaches the bottom. This approach ensures a seamless user experience by providing content on-demand without full page refreshes, making it highly effective for social media feeds, news articles, or image galleries.

💡Callback Function

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. In the video, the presenter explains how Throttle and Debounce techniques require a callback function to specify what action should be taken when the event (like scrolling) occurs. This is crucial for both techniques as they control the execution rate of this callback based on their respective logic.

💡Timer Variable

The timer variable is used within the Throttle function to keep track of the setTimeout calls. This allows the function to limit how often the callback is executed. The presenter mentions using a closure to share this timer variable across calls to the Throttle function, ensuring that subsequent calls can check if the timer is already set and act accordingly. This mechanism is central to how Throttle limits the rate of function execution.

💡SetTimeout

SetTimeout is a JavaScript method that executes a function after a specified number of milliseconds. It's instrumental in implementing Throttle and Debounce logic. In the context of Throttle, as explained in the video, SetTimeout is used to ensure the callback function is executed only once per specified time interval, thus preventing it from running too frequently during continuous events like scrolling.

💡Event Listener

An event listener is a procedure in JavaScript that waits for an event to occur, like a mouse click or a keypress. The presenter sets up an event listener for scroll events to trigger the Throttle function. This is a critical step in creating interactive web applications, as it allows developers to define how the application should respond to user inputs or actions.

💡Scroll Event

The scroll event is fired when the user scrolls through a container that has overflow content, like a webpage. In the video, scroll events are key to demonstrating the Throttle technique in the context of an infinite scroll implementation. By attaching a Throttle function to the scroll event, the presenter is able to load new content at a controlled rate, improving performance and user experience.

💡Document Object Model (DOM)

The DOM is a programming interface for web documents. It represents the page so that programs can change the document structure, style, and content. The presenter in the video interacts with the DOM to append new elements when the page is scrolled to the bottom, showcasing a practical use of JavaScript to dynamically modify web pages.

💡Closure

A closure is a feature in JavaScript where an inner function has access to the outer (enclosing) function's variables. The presenter uses closures in the Throttle function to allow the timer variable to be shared and manipulated across multiple invocations of the Throttle function. This concept is pivotal for understanding how Throttle maintains its internal state between events.

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

play00:01

那我們今天來介紹的是 Throttle

play00:03

就是節流

play00:05

那如果有看過我上一支影片在講 Debounce 的話

play00:07

你會發現說它其實和 Debounce 蠻像的

play00:10

當然有一些不同的地方

play00:12

等我們把 Throttle function 實作完再來簡單的講一下

play00:16

它跟 Debounce 有什麼不一樣

play00:18

今天要 Demo 的畫面會長這樣子

play00:21

昨天有一位觀眾跟我問問題

play00:25

那剛好他問的問題就可以直接用 Throttle 來解決

play00:27

我們就直接來看一下

play00:29

目前我畫面上有一些元素

play00:31

有一些文字在上面

play00:32

注意到我右邊的 Scrollbar 它目前的長度是這樣子

play00:36

其實現在這樣滑 在我去滾動我的 Scrollbar 的時候就已經觸發 Throttle 了

play00:41

我寫的判斷是說

play00:43

如果我的滾動軸已經滑到底部的話

play00:46

就去幫我加載 去載入新的元素進來

play00:50

這跟我們之前用 Observer API 做的方式很像

play00:53

你看我一直往下滾

play00:54

它就一直幫我長新的元素出來

play00:56

大概是這樣子

play00:58

那我們知道我們現在要做出 Infinite Scroll 的話 就直接開始

play01:03

那現在畫面上是沒有任何東西的

play01:06

那如果要實做 Infinite Scroll 的話 當然要有一些東西在畫面上

play01:10

所以我先簡單的長出 30 個 p 標籤

play01:14

這樣子就可以滾動了

play01:15

OK 沒有問題

play01:17

那接著就來到 JavaScript 的部分

play01:20

那我就直接去實作我的 Throttle 的 function

play01:24

好 那跟 Debounce 一樣 它一樣會有兩個參數需要丟進去

play01:28

第一個就是我們要執行的 function

play01:30

所以我叫它 callback

play01:32

第二個是延遲的時間叫做 time 那設定為 1 秒

play01:36

就是 1000ms

play01:37

這裡面了一樣 我們回傳一個 function

play01:41

那這邊要注意到的是 我這邊不使用 arrow function

play01:44

我這邊不使用 arrow function 那原因是什麼我等下會解釋一下

play01:48

就用正常的 function

play01:50

在裡面呢

play01:51

一樣 我們要先在一開始進來 Throttle function 的時候要有一個 timer 變數

play01:56

使用閉包讓使用 Throttle function 的可以去共享這個 timer 變數

play02:01

然後在裡面一樣 就去實作我的 setTimeout 就好了

play02:08

延遲時間是 1 秒

play02:11

在 setTimeout 裡面除了要去執行 callback 以外

play02:15

我們還要去把 timer 給清空

play02:18

那就直接把它設定為 null 就好了

play02:20

那會這樣做的原因是因為 它跟 Debounce 不一樣的地方在於

play02:24

如果我現在在滾動我的滾動軸的話

play02:27

那我現在執行麻 所以他應該要知道

play02:30

那就根據我設定給它的延遲時間 每隔 1 秒

play02:34

就去執行我 callback 裡面的內容

play02:36

每隔 1 秒就去執行我 callback 裡面的內容

play02:38

所以它跟 Debounce 不一樣

play02:40

Debounce 是在說我們停下來以後

play02:42

它才去執行我 callback 裡面的內容

play02:44

但 Throttle 節流就是說你目前有做這個動作嗎?

play02:48

有 那我就根據你給我的時間

play02:50

每隔幾秒要執行一次 我就去幫你執行

play02:55

但是我們現在寫成這樣子 還會有一個問題

play02:58

就是說如果我們已經有一個 timeout

play03:01

已經有一個計時器在跑了

play03:02

那如果我們又滾動我們的滾動軸的話

play03:05

那它是不是累積這個 累加這個 timeout 下去

play03:08

但這並不是我們要結果

play03:09

所以我們還要在這邊去做個判斷

play03:11

判斷說

play03:12

我的這個 timer 目前有沒有值

play03:15

好 如果有的話你就幫我 return 就好了 什麼事都不用幫我做

play03:18

那如果沒有的話 它就會去跑下面這一行程式碼

play03:21

去設定給它一個 timeout

play03:23

好那就先這樣子 其實這樣寫完就是一個 Throttle 的 function 了

play03:27

所以我們現在要去寫的是 Infinite Scroll 的邏輯

play03:31

所以我們的 Throttle function 已經寫完了喔

play03:34

那但是等下還會有一些

play03:36

參數傳遞的問題

play03:37

我到最後再來講一下

play03:42

那我先 console.log 確定一下有沒有問題

play03:46

那我在我的

play03:47

document 去設定一個監聽器

play03:49

當我的滾動軸滾動的時候 去觸發這個 event

play03:53

那這邊我就可以直接去使用 Throttle function 了

play03:57

那裡面我們就只需要傳遞一個參數進去

play03:59

就是我們的 callback

play04:01

就直接把我們的 scroll function 丟進去

play04:03

那第二個參數我可以填或是不填都可以

play04:06

如果我要去填寫它延遲執行的時間 就可以在第二個參數去傳遞

play04:11

但這邊就不用了 就讓它延遲 1 秒執行就好了

play04:14

那這邊我先測試一下 我先儲存

play04:17

然後重新整理一下

play04:19

然後我現在去滾動一下我的滾動軸

play04:22

你就會發現說 我目前只要滾動我的滾動軸的話 它每隔 1 秒

play04:28

就會在我的 console

play04:29

印出 scroll

play04:30

也就是我們要的效果了

play04:32

我們已經達到所謂的延遲執行了

play04:35

那下一個步驟就是要去判斷說

play04:37

我們這個 Scrollbar 是不是已經到底部了

play04:39

如果是的話 我們就去加載 去載入更多的元素到我們的畫面

play04:45

所以我這邊去 很簡單的寫一下這個邏輯

play04:48

去取得 client 的 height

play04:51

那這邊可能會根據不同的瀏覽器有不同的寫法

play04:55

那我記得 因為我之前好像寫 document.body

play04:59

然後 .clientHeight 的話 它好像取得不到東西

play05:02

我只能寫這個 documentElement

play05:04

所以如果你要跨瀏覽器的話

play05:07

你就需要寫成這樣子

play05:09

document.body.clientHeight

play05:12

這個比較確保比較保險一點的寫法如果你不確定

play05:16

你這個功能在其他瀏覽器能不能運作的話 就寫成這樣子

play05:20

但是我這邊先簡寫成前面這樣就好了

play05:23

就直接去取得 documentElement 裡面的 clientHeight

play05:28

那再來是我要去取得 scrollTop

play05:46

那這邊可以做一個簡單的運算

play05:50

它固定的公式是這樣子的

play05:52

假設我們的 scrollTop 加上我們的 clientHeight

play05:58

如果等於 scrollHeight 的話

play06:01

代表它已經到底部了

play06:03

但這樣寫其實會有一個問題 我們先來看一下會不會有這個問題出現

play06:07

所以這邊先把它 console 出來

play06:10

把我的 scrollTop 加 clientHeight

play06:13

這個數值加起來後 顯示在 console

play06:16

然後還有我們的 scrollHeight

play06:25

現在往下滑動 你會看到說它已經再執行運算了

play06:28

但你會發現說 有這個小數點 浮點數的這個問題

play06:32

所以要是我滑到底部的話

play06:35

他有可能不會等於

play06:37

可能會差 1 或是少 1 都有可能

play06:40

所以比較確保的做法

play06:42

通常可能會在這邊再去加一點數值

play06:46

判斷一下這些數值運算完之後加10

play06:50

是不是大於我的 scrollHeight

play06:52

就不要把它判斷說 完全等於

play06:54

所以現在這樣寫完之後再重新整理一下 然後滑到最底部

play07:00

你會看到說 我的這個 bottom 文字出現了

play07:03

這是進到 if 裡面才會有這個文字出現

play07:06

所以我們現在可以在裡面去判斷說

play07:08

我們現在可以在裡面知道說 它已經滑到底部了 所以去載入更多元素進來

play07:13

那載入更多元素這件事情蠻簡單的 我們寫一個 for 迴圈

play07:28

我們去建立一個 新的 p 標籤

play07:30

然後這個 p 標籤就隨便給一個文字

play07:36

最後就我的 result 我的 result 在這邊

play07:39

在這塊裡面

play07:40

就直接用 appendChild

play07:43

新建立出來的這個 node

play07:45

p 標籤 node 直接丟進去

play07:48

所以如果我現在執行下來的話

play07:51

知道我到底部之後 就會直接渲染新的 p 標籤出來 在我的這個畫面上

play07:56

所以這個 Infinite Scroll 已經完成了 我們來看一下喔

play07:59

先滑到最上面 儲存一下

play08:07

只要滑到底部

play08:08

就會一直載入新的元素出來

play08:12

那如果你想要提前 不想要滑到底部才去載入的話

play08:17

如果想要提前的話 可以使用另外一個算法 這邊去改一下判斷

play08:25

去判斷說我們的 scrollTop

play08:28

加上 clientHeight

play08:30

除與我們的 scrollHeight

play08:33

是不是大於等於0.9

play08:36

1 就是底部的意思 (100%) 那 0.9 就是 90% 的位置

play08:40

一樣可以儲存一下

play08:44

慢慢滑下去

play08:46

我現在沒有滑到底 但是我慢慢的滑 滑到大概 90% 的位置

play08:50

就會去載入我新的元素出來了

play08:52

所以如果你不想讓它到底部才去執行這件事情的話

play08:56

你就可以這樣子去判斷

play08:58

那 Throttle 的話就是這樣子 那我最後再講一個

play09:02

就是說 我們剛剛前面有講到

play09:04

我們的這個 function 是使用一般 function 不是 arrow function

play09:09

那是因為我的 callback

play09:11

它沒有參數的傳遞 也沒有 this 的問題 所以我才敢這樣寫

play09:15

那如果今天

play09:16

你的這個 callback 裡面可能有牽扯到 args 或是 this 的問題

play09:21

你就需要在這個 return 裡面去做一個綁定 this

play09:31

就把它寫成一個變數在外面去綁定

play09:33

然後在 timeout 裡面丟進去

play09:36

所以現在這邊也不能這樣寫了 如果你要做 this 的綁定和參數的傳遞的話

play09:42

就要用 apply

play09:47

然後第一個就要丟 context 進去 然後是我的 args

play09:51

其實這樣執行起來是沒有差 以我這個例子來說是沒有差的

play09:55

因為我沒有參數的傳遞 那如果你今天有參數的傳遞又要綁定 this 的話

play09:59

就要這樣去寫

play10:01

那針對 Throttle 的介紹應該就到這邊了

play10:05

也非常感謝那一位觀眾給我的建議

play10:09

好那我們可以知道說

play10:11

跟 Debounce 的比較就我們前面有講過一遍了嘛

play10:13

Debounce 是當我動作停下來

play10:15

等幾秒後沒有再繼續執行的時候

play10:18

它才去幫我執行我的 callback

play10:20

就是說我 function 裡面的內容

play10:22

Throttle 不一樣的地方就是說 我現在有在執行這個動作 那你每隔幾秒就要幫我執行 callback 裡面的內容

Rate This

5.0 / 5 (0 votes)

Related Tags
JavaScriptThrottleDebounceInfinite ScrollWeb DevelopmentFunction TimingEvent HandlingProgramming TutorialCode OptimizationPerformance Improvement