In which order are event listeners added to the call stack?

171 Views Asked by At

I am writing a scroll synchronization module in js, and am encountering some very unexpected behavior with how scroll events are firing. Starting with the code:

const attach = (element) => {
  // synchronizedElements is in scope because of closures
  const onScrollListener = () => {

    // first detach all other listeners
    synchronizedElements.current.forEach((listener, el) => 
      if(el !== element) el.removeEventListener('scroll', listener)
    );
    

    // synchronize all of the other elements with the leader
    syncFollowers({leader: element, synchronizedElements});

    // then re-attach all of the other listeners
    synchronizedElements.current.forEach((listener, el) => 
      if(el !== element) el.addEventListener('scroll', listener)
    );
  }
  synchronizedElements.current.add(element, onScrollListener);
  element.addEventListener('scroll', synchronizedElements);
}

With this, I would expect the first element to be scrolled to have its listener invoked. It would assume the role of leader and remove all of the other elements; (followers) so it can move their scroll positions without them firing their onScrollListeners in response. And then reattach the listeners so they can be leaders again. This is critical so the followers don't also try to do the exact same thing.

Instead, what happens is that the followers' listeners all also get invoked immediately after the leader's is done. All I'd like to do is bypass the non-leaders' scroll events while the leader is scrolling.

I'm wondering if the removeEventListener + addEventListener are queued and not actually executed until this entire function completes, thus the followers still have their listeners attached when the leader moves them. Any thoughts?

0

There are 0 best solutions below