You can achieve smooth scrolling animations by using requestAnimationFrame and watching the scroll position within it, bypassing the blocking nature of the scroll event handler.
`scroll` listeners are not blocking, however `wheel` ones are. If you've tried to implement a parallax effect in JS you may have noticed the subtle differences on timing between these two (wheel fires before the scroll position is updated, scroll afterwards). That said, yielding immediately within a listener (like you recommend) is indeed a best practice.
This coupled with storing the scroll position and only executing code when it actually changes is the gold standard IMO. Works fantastically well on mobile too.