wesleybliss
4/28/2018 - 9:33 AM

Debounce a function

Debounce a function

/**
 * Creates a debounced monad to allow a method to be called
 * many times, but only execute after N seconds has elapsed
 * 
 * @param  {Function} func        Method to call
 * @param  {Number}   wait        Timeout, in milliseconds
 * @param  {Boolean}  [immediate] Optionally skip the wait
 * @return {Function}             Debounced monad that can be called multiple times
 */
export function debounce(func, wait, immediate) {
    let timeout
    return function (...args) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            timeout = null
            if (!immediate) func.apply(this, args)
        }, wait)
        if (immediate && !timeout) func.apply(this, [...args])
    }
}

// Example

const prom = (a, b) => new Promise(resolve => {
    setTimeout(() => resolve(a + b), 1000)
})

const fun = async (a, b) => {
    try {
        const res = await prom(a, b)
        console.log(a, '+', b, '=', res)
    }
    catch (e) {
        return null
    }
}

const funDebounced = debounce(fun, 600)

funDebounced(1, 2)
funDebounced(3, 4)
funDebounced(5, 6)
funDebounced(7, 8)
funDebounced(9, 10)

// Outputs: 9 '+' 10 '=' 19