UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

1 lines • 3.55 kB
{"version":3,"file":"throttleStrategy.cjs","sources":["../../../src/strategies/throttleStrategy.ts"],"sourcesContent":["import type { ThrottleStrategy, ThrottleStrategyOptions } from './types'\nimport type { Transaction } from '../transactions'\n\n/**\n * Creates a throttle strategy that ensures transactions are evenly spaced\n * over time.\n *\n * Provides smooth, controlled execution patterns ideal for UI updates like\n * sliders, progress bars, or scroll handlers where you want consistent\n * execution timing.\n *\n * @param options - Configuration for throttle behavior\n * @returns A throttle strategy instance\n *\n * @example\n * ```ts\n * // Throttle slider updates to every 200ms\n * const mutate = usePacedMutations({\n * onMutate: (volume) => {\n * settingsCollection.update('volume', draft => { draft.value = volume })\n * },\n * mutationFn: async ({ transaction }) => {\n * await api.updateVolume(transaction.mutations)\n * },\n * strategy: throttleStrategy({ wait: 200 })\n * })\n * ```\n *\n * @example\n * ```ts\n * // Throttle with leading and trailing execution\n * const mutate = usePacedMutations({\n * onMutate: (data) => {\n * collection.update(id, draft => { Object.assign(draft, data) })\n * },\n * mutationFn: async ({ transaction }) => {\n * await api.save(transaction.mutations)\n * },\n * strategy: throttleStrategy({\n * wait: 500,\n * leading: true,\n * trailing: true\n * })\n * })\n * ```\n */\nexport function throttleStrategy(\n options: ThrottleStrategyOptions,\n): ThrottleStrategy {\n const leading =\n options.leading === true ||\n (options.leading === undefined && options.trailing !== true)\n const trailing = options.trailing !== false\n let nextAllowedAt = Number.NEGATIVE_INFINITY\n let trailingTimeout: ReturnType<typeof setTimeout> | undefined\n let pendingCallback: (() => Transaction) | undefined\n\n return {\n _type: `throttle`,\n options,\n execute: <T extends object = Record<string, unknown>>(\n fn: () => Transaction<T>,\n ) => {\n const now = Date.now()\n if (leading && trailingTimeout === undefined && now >= nextAllowedAt) {\n nextAllowedAt = now + options.wait\n fn()\n return\n }\n if (!trailing) return false\n pendingCallback = fn as () => Transaction\n if (trailingTimeout === undefined) {\n const delay = leading ? Math.max(0, nextAllowedAt - now) : options.wait\n trailingTimeout = setTimeout(() => {\n trailingTimeout = undefined\n nextAllowedAt = Date.now() + options.wait\n const callback = pendingCallback\n pendingCallback = undefined\n callback?.()\n }, delay)\n }\n return\n },\n cleanup: () => {\n // Pending work keeps its timer until the scheduled callback runs.\n },\n }\n}\n"],"names":[],"mappings":";;AA8CO,SAAS,iBACd,SACkB;AAClB,QAAM,UACJ,QAAQ,YAAY,QACnB,QAAQ,YAAY,UAAa,QAAQ,aAAa;AACzD,QAAM,WAAW,QAAQ,aAAa;AACtC,MAAI,gBAAgB,OAAO;AAC3B,MAAI;AACJ,MAAI;AAEJ,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA,SAAS,CACP,OACG;AACH,YAAM,MAAM,KAAK,IAAA;AACjB,UAAI,WAAW,oBAAoB,UAAa,OAAO,eAAe;AACpE,wBAAgB,MAAM,QAAQ;AAC9B,WAAA;AACA;AAAA,MACF;AACA,UAAI,CAAC,SAAU,QAAO;AACtB,wBAAkB;AAClB,UAAI,oBAAoB,QAAW;AACjC,cAAM,QAAQ,UAAU,KAAK,IAAI,GAAG,gBAAgB,GAAG,IAAI,QAAQ;AACnE,0BAAkB,WAAW,MAAM;AACjC,4BAAkB;AAClB,0BAAgB,KAAK,IAAA,IAAQ,QAAQ;AACrC,gBAAM,WAAW;AACjB,4BAAkB;AAClB,qBAAA;AAAA,QACF,GAAG,KAAK;AAAA,MACV;AACA;AAAA,IACF;AAAA,IACA,SAAS,MAAM;AAAA,IAEf;AAAA,EAAA;AAEJ;;"}