Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
enh(lazyTimer): options minInterval and maxDelay
Signed-off-by: Max <[email protected]>
  • Loading branch information
max-nextcloud committed Feb 18, 2023
commit f16693d89d169f131fc5f02391d8f00c63acd618
25 changes: 18 additions & 7 deletions src/helpers/lazy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,23 @@
*/

/**
* Call callback in intervals that double
*
* Returns a handle to modify the interval:
* - handle.wakeUp() resets it to the minimum.
* - handle.sleep() uses maximum interval right away.
* - handle.interval can be used to clear the interval:
* `clearInterval(handle.interval)`
*
* @param {Function} callback to be triggered by the timer
* @param {object} options optional
* @param {number} options.minInterval minimum interval between two calls
* @param {number} options.maxDelay maximum factor to multiply the interval by
* @return {Function} handle to modify behavior
*/
function lazyTimer(callback) {
const fn = lazy(callback)
fn.interval = setInterval(fn, 300)
function lazyTimer(callback, { minInterval = 300, maxDelay = 16 } = {}) {
const fn = lazy(callback, { maxDelay })
fn.interval = setInterval(fn, minInterval)
return fn
}

Expand All @@ -48,16 +59,16 @@ export { lazyTimer }
*
* @param {Function} inner function to be called
* @param {object} options optional
* @param {number} options.maxInterval maximum interval between two calls to inner
* @param {number} options.maxDelay maximum interval between two calls to inner
*/
export function lazy(inner, { maxInterval = 16 } = {}) {
export function lazy(inner, { maxDelay = 16 } = {}) {
let count = 0
let interval = 1
const result = (...args) => {
count++
if (count === interval) {
count = 0
interval = Math.min(interval * 2, maxInterval)
interval = Math.min(interval * 2, maxDelay)
return inner(...args)
}
}
Expand All @@ -66,7 +77,7 @@ export function lazy(inner, { maxInterval = 16 } = {}) {
interval = 1
}
result.sleep = () => {
interval = maxInterval
interval = maxDelay
}
return result
}
24 changes: 18 additions & 6 deletions src/tests/helpers/lazy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@ describe('lazy timer', () => {
jest.useRealTimers()
})

test('stays at same interval once it reached maxInterval', () => {
test('allows configuring min and max intervals', () => {
jest.useFakeTimers()
const callback = jest.fn();
const timer = lazyTimer(callback, { minInterval: 10, maxDelay: 2 });
expect(callback).not.toBeCalled();
jest.advanceTimersByTime(40);
expect(callback).toHaveBeenCalledTimes(2); // 10, 30
jest.advanceTimersByTime(40);
expect(callback).toHaveBeenCalledTimes(4); // 50, 70
jest.useRealTimers()
})

test('stays at same interval once it reached maxDelay', () => {
jest.useFakeTimers()
const callback = jest.fn();
const timer = lazyTimer(callback);
Expand Down Expand Up @@ -50,7 +62,7 @@ describe('lazy timer', () => {
jest.useRealTimers()
})

test('goes to maxInterval when sleep is called', () => {
test('goes to maxDelay when sleep is called', () => {
jest.useFakeTimers()
const callback = jest.fn();
const timer = lazyTimer(callback);
Expand Down Expand Up @@ -114,22 +126,22 @@ describe('lazy function', () => {

test('respects skipAtMost option', () => {
const inner = jest.fn()
const fn = lazy(inner, { maxInterval: 4 })
const fn = lazy(inner, { maxDelay: 4 })
callNTimes(20, fn)
expect(inner.mock.calls.map(call => call[0])).toEqual([1,3,7,11,15,19])
})

test('maxInterval defaults to 16', () => {
test('maxDelay defaults to 16', () => {
const inner = jest.fn()
const fn = lazy(inner)
callNTimes(64, fn)
expect(inner.mock.calls.map(call => call[0])).toEqual([1,3,7,15,31,47,63])
})

test('Uses maxInterval after sleep was called', () => {
test('Uses maxDelay after sleep was called', () => {
const inner = jest.fn()
let count = 0
const lazyFn = lazy(() => inner(count), { maxInterval: 6 })
const lazyFn = lazy(() => inner(count), { maxDelay: 6 })
const trigger = () => {
count++
lazyFn()
Expand Down