另一個流行的前端面試問題。它測試受訪者對 JS、性能和 FE 系統設計的知識。
這是前端面試問題系列的第二個問題。如果您希望提高準備程度或保持最新狀態,請考慮註冊 FrontendCamp。
去抖和節流的工作原理相同 - 延遲東西 - 但仍然有非常不同的方法和用例。
這兩個概念對於開發高效能應用程式都很有用。 您每天造訪的幾乎所有網站都以某種方式使用去抖和節流。
去抖動的一個眾所周知的用例是預先輸入(或自動完成)。
假設您正在為一個擁有數千種產品的電子商務網站建立搜尋功能。當使用者嘗試搜尋某些內容時,您的應用程式將進行 API 呼叫以取得與使用者的查詢字串相符的所有產品。
const handleKeyDown = async (e) => { const { value } = e.target; const result = await search(value); // set the result to a state and then render on UI } <Input onKeyDown={handleKeyDown} />
這種方法看起來不錯,但有一些問題:
解決這些問題的方法是去抖動。
基本想法是等到使用者停止輸入。我們將延遲 API 呼叫。
const debounce = (fn, delay) => { let timerId; return function(...args) { const context = this; if (timerId) { clearTimeout(timerId); }; timerId = setTimeout(() => fn.call(context, ...args), delay); } } const handleKeyDown = async (e) => { const { value } = e.target; const result = await search(value); // set the result to a state and then render on UI } <Input onKeyDown={debounce(handleKeyDown, 500)} />
我們擴展了現有程式碼以利用去抖動。
去抖動函數是通用實用函數,它接受兩個參數:
在函數內部,我們使用 setTimeout 來延遲實際的函數(fn)呼叫。如果在計時器耗盡之前再次呼叫 fn,計時器將重設。
透過我們更新的實現,即使使用者輸入 15 個字符,我們只會進行 1 次 API 呼叫(假設每次按鍵的時間少於 500 毫秒)。這解決了我們開始建立此功能時遇到的所有問題。
在生產程式碼庫中,您不必編寫自己的去抖動實用函數。您的公司很可能已經使用了像 lodash 這樣具有這些方法的 JS 實用程式庫。
嗯,去抖動對於效能來說非常有用,但在某些情況下,我們不想在收到更改通知之前等待 x 秒。
想像一下您正在建立一個協作工作空間,例如 Google Docs 或 Figma。關鍵功能之一是用戶應該即時了解其他用戶所做的更改。
到目前為止我們只知道兩種方法:
這就是節流的用武之地。它位於上述兩種方法的中間。基本想法是 - 定期通知 - 不是在最後也不是在每次按鍵時通知,而是定期通知。
const throttle = (fn, time) => { let lastCalledAt = 0; return function(...args) { const context = this; const now = Date.now(); const remainingTime = time - (now - lastCalledAt); if (remainingTime <= 0) { fn.call(context, ...args); lastCalledAt = now; } } } const handleKeyDown = async (e) => { const { value } = e.target; // save it DB and also notify other peers await save(value); } <Editor onKeyDown={throttle(handleKeyDown, 1000)} />
我們修改了現有程式碼以利用節流功能。它需要兩個參數:
實作非常簡單。我們將函數上次呼叫的時間儲存在lastCalledAt中。下次,當進行函數呼叫時,我們檢查時間是否已經過去,然後才執行 fn。
我們已經快到了,但是這個實作有一個錯誤。如果最後一次使用某些資料的函數調用是在時間間隔內進行的,並且此後沒有進行任何調用,該怎麼辦?根據我們目前的實現,我們將丟失一些數據。
為了解決這個問題,我們將參數儲存在另一個變數中,並啟動一個逾時,以便在沒有收到事件時稍後呼叫。
const throttle = (fn, time) => { let lastCalledAt = 0; let lastArgs = null; let timeoutId = null; return function(...args) { const context = this; const now = Date.now(); const remainingTime = time - (now - lastCalledAt); if (remainingTime <= 0) { // call immediately fn.call(context, ...args); lastCalledAt = now; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } } else { // call later if no event is received lastArgs = args; if (!timeoutId) { timeoutId = setTimeout(() => { fn.call(context, ...lastArgs); lastCalledAt = Date.now(); lastArgs = null; timeoutId = null; }, remainingTime); } } } }
此更新的實作可確保我們不會錯過任何資料。
Lodash 也提供了節流實用功能。
前端營
洛達什
以上是去抖和節流的詳細內容。更多資訊請關注PHP中文網其他相關文章!