dom icon indicating copy to clipboard operation
dom copied to clipboard

Add EventListener Sub Flags [Suggestion] [Feature Request]

Open Seagat2011 opened this issue 3 years ago • 2 comments

Add EventListener Sub Flags

EventListeners allow the addition of a preset delay before firing the callback parameter (event throttling). However to reduce bandwith when polling a remote server, and because the number of keystrokes-, scrolling-, mousemove- or resize events is non deterministic, it is more useful to "batch" events and fire the callback once.

This may be so common in use today it may be beneficial to add it to the standard

REFERENCE Adding Javascript Debounce And Throttling Controls [ https://youtu.be/cjIswDCKgu0 ] TC39 AddEventListener Sub Flags [ https://es.discourse.group/t/add-eventlistener-sub-flags/1277 ]

// CURRENT //

const input = document.getElementById("input")
const defaultText = document.getElementById("defaultText")
const debouncedText = document.getElementById("debouncedText")
const throttleText = document.getElementById("throttleText")
const mouseEvents = document.getElementById("mouseEvents")

function debounce(cb, delay = 1000){
    let timeout = null
    return (...args) => {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            cb(...args)
        }, delay)
    }
}

const updateDebouncedText = debounce(text => {
    defaultText.textContent = text
}, 250)

function throttle(cb, delay = 1000){
    let shouldWait = false
    let waitingArgs = null
    const timeoutFunc = () => {
        if(shouldWait == null){
            shouldWait = false
        } else {
            cb(...waitingArgs)
            waitingArgs = null
            setTimeout(timeoutFunc, delay)
        }
    }
    return (...args) => {
        if (shouldWait){
            waitingArgs = args
            return
        }
        cb(...args)
        shouldWait = true
        setTimeout(timeoutFunc, delay)
    }
}

const updateThrottleText = throttle(text => {
    defaultText.textContent = text
}, 250)

input.addEventListener("input", e => {
    defaultText.textContent = e.target.value
    updateDebouncedText(e.target.value)
    updateThrottleText(e.target.value)
}, false)

// NEW //

input.addEventListener("post.batch.input", e => {
    debouncedText.textContent = e.target.value
}, 250) // fire callback on input event[s], batched as a single event, during delay (ie "a","b" == "ab") //

input.addEventListener("pre.throttle.input", e => {
    debouncedText.textContent = e.target.value
}, 250) // fire callback only on last event received during delay (ie "a","b" == "b") //

input.addEventListener("pre.throttle.mousemove", e => {
    mouseEvents.textContent = e.target.value
}, 250) // fire callback only on last event received during delay (ie "[100,30]","[-50,30]" == "[-50,30]") //

Seagat2011 avatar Apr 04 '22 03:04 Seagat2011

I think it would be good to know what all mechanisms are being used for this currently to know what features really would be useful. Things like, do JS frameworks store the whole composePath() and all the targets, or just .target? And what do they do with various properties in the events? I'm a tiny bit worried adding an easy way to keep lots of memory alive through the event target objects.

Batching isn't very clear to me. How would that work, what would be the values of the properties in the event?

(It isn't clear to me what post. and pre. are supposed to mean in the example)

smaug---- avatar Aug 12 '22 10:08 smaug----

Related discussion about adding adding event throttling and debouncing to AddEventListenerOptions

https://discourse.wicg.io/t/add-event-throttling-and-debouncing-to-addeventlisteneroptions/2436

simevidas avatar Sep 19 '23 18:09 simevidas