From e9769b07218601352f3164d7dfb0f8b8252aa6ec Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Sat, 8 Oct 2022 15:03:44 +0100 Subject: [PATCH] Add throttle utility as an improved debounce --- packages/frontend-core/src/utils/utils.js | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/packages/frontend-core/src/utils/utils.js b/packages/frontend-core/src/utils/utils.js index 587d057351..ed76f13494 100644 --- a/packages/frontend-core/src/utils/utils.js +++ b/packages/frontend-core/src/utils/utils.js @@ -4,6 +4,8 @@ * @param fn the async function to run * @return {Promise} a sequential version of the function */ +import { lastIndexOf } from "lodash/array" + export const sequential = fn => { let queue = [] return async (...params) => { @@ -40,3 +42,37 @@ export const debounce = (callback, minDelay = 1000) => { }) } } + +/** + * Utility to throttle invocations of a synchronous function. This is better + * than a simple debounce invocation for a number of reasons. Features include: + * - First invocation is immediate (no initial delay) + * - Every invocation has the latest params (no stale params) + * - There will always be a final invocation with the last params (no missing + * final update) + * @param callback + * @param minDelay + * @returns {Function} a throttled version function + */ +export const throttle = (callback, minDelay = 1000) => { + let lastParams + let stalled = false + let pending = false + const invoke = (...params) => { + lastParams = params + if (stalled) { + pending = true + return + } + callback(...lastParams) + stalled = true + setTimeout(() => { + stalled = false + if (pending) { + pending = false + invoke(...lastParams) + } + }, minDelay) + } + return invoke +}