timer.js
const hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function'; const now = hasNativePerformanceNow ? () => performance.now() : () => Date.now(); export function cancelTimeout(timeoutID) { cancelAnimationFrame(timeoutID.id); } export function requestTimeout(callback, delay) { const start = now(); function tick() { if (now() - start >= delay) { callback.call(null); } else { timeoutID.id = requestAnimationFrame(tick); } } const timeoutID = { id: requestAnimationFrame(tick), }; return timeoutID; }index.jsx
const IS_SCROLLING_DEBOUNCE_INTERVAL = 2000; class Home extends React.Component { constructor(props) { super(props); this.onScrollVertical = this.onScrollVertical.bind(this); this.resetIsScrolling = this.resetIsScrolling.bind(this); } onScrollVertical(event) { if (this.resetIsScrollingTimeoutId) { cancelTimeout(this.resetIsScrollingTimeoutId); } this.resetIsScrollingTimeoutId = requestTimeout( this.resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL, ); } resetIsScrolling() { this.resetIsScrollingTimeoutId = null; console.log('handle debounce...'); } render() { return ( <div style={{ height: '80px', overflow: 'auto' }} onScroll={this.onScrollVertical} > { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((item) => ( <div style={{ height: '50px' }} key={item}>{item}</div> )) } </div> ); } } export default Home;