更新日曆的防抖策略
啊,了解了!您的編輯介面是
使用者在編輯一個欄位時(例如行程標題),可能只是 打字過程中的中間狀態 ,並不是最終想要的結果。例如,打一個字就觸發一次 change,然後馬上又打下一個字。如果每次 change 事件都立即觸發 update/patch API 調用,就會產生大量 不必要 的 API 請求,發送的都是中間狀態的數據。這不僅可能(儘管機率仍然很低)更快地消耗 API 配額(尤其是每秒速率限制),更重要的是,它 效率低下 ,且可能因為網路延遲等原因導致最終日曆上的狀態與使用者介面不完全同步 (例如,使用者輸入很快,但只有部分中間狀態的 API 更新成功了)。
防抖 (Debounce): 原理: 當 change 事件觸發時,不立即 執行 API 更新,而是啟動一個計時器 (例如 500 毫秒或 1 秒)。如果在計時器到期之前,又 有新的 change 事件觸發,則重置 計時器。只有當計時器成功到期 (表示使用者在一段時間內沒有再輸入/修改)時,才執行一次 API 更新操作,使用最新 的數據。效果: 使用者連續快速輸入時,只會在他們停止輸入一段時間後 才觸發 API 更新。大大減少了 API 調用次數。實現: 需要自己編寫防抖函數,或者使用現成的 JavaScript 庫(如 Lodash 的 _.debounce)。
// 假設您有一個 debounce 函數 const debouncedUpdateCalendar = debounce(async (itemId, updatedData) => { try { const token = await getAuthToken(true); // 獲取對應的 eventId const mapping = await chrome.storage.local.get([itemId]); // 假設 eventId 存在映射裡 const eventId = mapping[itemId]?.googleCalendarId; if (eventId) { console.log(`Debounced: Updating event ${eventId} for item ${itemId}`); // 調用 patch API 更新日曆 await patchEventToCalendar(eventId, updatedData, token); } } catch (error) { console.error('Debounced update error:', error); } }, 1000); // 延遲 1 秒 // 在您的 change 事件處理器中: formField.addEventListener('change', function() { const itemId = /* 獲取當前編輯項目的 ID */; const currentData = /* 從表單獲取當前的完整數據 */; // 觸發防抖函數,傳入最新數據 debouncedUpdateCalendar(itemId, currentData); // *** 注意:您仍然可以立即更新 chrome.storage.local *** // setList(updatedLocalList); // 本地儲存可以即時更新 });節流 (Throttle): 原理: 在一定時間間隔內(例如每 2 秒),最多只執行一次 API 更新操作。如果在間隔內觸發了多次 change 事件,只有第一次(或最後一次,取決於實現)會觸發更新,其他的會被忽略,直到下一個時間間隔。效果: 限制了 API 調用的頻率上限。實現: 也需要自己寫或用庫(如 Lodash 的 _.throttle)。對於表單輸入,防抖通常比節流更合適。
只在失去焦點 (blur) 時更新: 不監聽 change,而是監聽輸入框的 blur 事件(當使用者點擊到其他地方,輸入框失去焦點時觸發)。這樣可以確保使用者完成了一個欄位的輸入後再觸發更新。但如果使用者直接關閉頁面可能不會觸發。顯式的「保存」按鈕(雖然您沒有): 這是最傳統但也最可靠的方式,使用者明確表示編輯完成。
強烈建議使用「防抖 (Debounce)」 策略來處理 API 更新調用。這能在使用者停止編輯一小段時間後,才用最新的數據執行一次更新,既保證了最終數據的提交,又避免了過於頻繁的 API 請求。本地 chrome.storage.local 的更新仍然可以(也應該)在每次 change 時即時進行,因為這個操作成本很低。
留言
張貼留言