import { createDeferred } from './promise' ; import type { AnyToAnyFnSignature } from '../misc/functions' ; import type { Deferred } from './promise' ; /** Throttled<F> is a function wrapper type for a function decorated via throttle */ export interface Throttled < F extends AnyToAnyFnSignature > { /** Throttled method signature */ ( ... args ) : void ; /** Promise of throttled function call */ promise : Promise < ReturnType < F > | void > ; } param fn param threshold param thisArg export function throttle < F extends AnyToAnyFnSignature > ( fn , threshold = 250 , thisArg ? ) { let last ; let timeout = null ; let deferred = null ; function throttledSubject ( ... args ) { const now = Date . now ( ) ; if ( ! last || now >= last + threshold ) { last = now ; fn . apply ( this , args ) ; } deferred = deferred || createDeferred ( ) ; ( typeof timeout === 'number' ) && clearTimeout ( timeout ) ; timeout = window . setTimeout ( ( ) => { last = now ; timeout = null ; deferred ! . resolve ( fn . apply ( thisArg || this , args ) ) ; deferred = null ; } , threshold ) ; } Object . defineProperty ( throttledSubject , 'promise' , { get : ( ) => deferred ? deferred . promise : Promise . resolve ( ) } ) ; return throttledSubject as Throttled < F > ; }