import { done } from './util' ; export function debounce ( delay ) { return decorate ( ( fn , key ) => { const timerKey = `$debounce$${ key }` ; return function ( this , ... args ) { clearTimeout ( this [ timerKey ] ) ; this [ timerKey ] = setTimeout ( ( ) => fn . apply ( this , args ) , delay ) ; } ; } ) ; } export const throttle = decorate ( _throttle ) ; function _throttle < T > ( fn , key ) { const currentKey = `$throttle$current$${ key }` ; const nextKey = `$throttle$next$${ key }` ; const trigger = function ( this , ... args ) { if ( this [ nextKey ] ) { return this [ nextKey ] ; } if ( this [ currentKey ] ) { this [ nextKey ] = done ( this [ currentKey ] ) . then ( ( ) => { this [ nextKey ] = undefined ; return trigger . apply ( this , args ) ; } ) ; return this [ nextKey ] ; } this [ currentKey ] = fn . apply ( this , args ) as Promise < T > ; const clear = ( ) => this [ currentKey ] = undefined ; done ( this [ currentKey ] ) . then ( clear , clear ) ; return this [ currentKey ] ; } ; return trigger ; } function decorate ( decorator ) { return ( _target , key , descriptor ) => { let fnKey = null ; let fn = null ; if ( typeof descriptor . value === 'function' ) { fnKey = 'value' ; fn = descriptor . value ; } else if ( typeof descriptor . get === 'function' ) { fnKey = 'get' ; fn = descriptor . get ; } if ( ! fn || ! fnKey ) { throw new Error ( 'not supported' ) ; } descriptor [ fnKey ] = decorator ( fn , key ) ; } ; }