All files / src throttle.ts

0% Statements 0/27
0% Branches 0/23
0% Functions 0/3
0% Lines 0/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69                                                                                                                                         
/*!
 * Copyright (c) Microsoft. All rights reserved.
 * Licensed under the MIT license. See LICENSE file in the project.
 */
/* eslint-disable @typescript-eslint/no-this-alias */
// https://stackoverflow.com/questions/27078285/simple-throttle-in-js
 
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
export interface ThrottleOptions {
	leading: boolean
	trailing: boolean
}
/**
 * Debounces function based on options provided
 * @param func - function to throttle
 * @param wait - time in milliseconds
 * @param options - optional object param to control timing, ex. \{trailing: false, leading: true\}
 */
export function throttle(
	func: (...args: any[]) => any,
	wait = 100,
	options?: ThrottleOptions,
): any {
	let context: any
	let lastArgs: any
	let result: any
	let timeout: any = null
	let previous = 0
	const currentOptions: ThrottleOptions = options
		? options
		: { leading: false, trailing: false }

	const later = function (): void {
		previous = currentOptions.leading === false ? 0 : Date.now()
		timeout = null
		result = func.apply(context, lastArgs)
		if (!timeout) {
			context = lastArgs = null
		}
	}
	return function (this: any, ...args: any[]) {
		const now = Date.now()
		if (!previous && currentOptions.leading === false) {
			previous = now
		}
		const remaining = wait - (now - previous)
		context = this
		lastArgs = args
		if (remaining <= 0 || remaining > wait) {
			if (timeout) {
				clearTimeout(timeout)
				timeout = null
			}
			previous = now
			result = func.apply(context, lastArgs)
			if (!timeout) {
				context = lastArgs = null
			}
		} else if (!timeout && currentOptions.trailing !== false) {
			timeout = setTimeout(later, remaining)
		}
		return result
	}
}