[Frontend Note] A quick recap on throttle and debounce

Functions we use often but do not always fully understand

Posted by Jamie on Tuesday, June 27, 2023

Frontend performance: debounce and throttle

Preface

Looking back, when I first ran into debounce and throttle, I thought “what kind of weird jargon is this, why make things so complicated?” After a quick search I learned they are solutions for improving performance and avoiding stack overflow, and after that, whenever I ran into a similar feature, I would just reach for lodash.debounce and call it a day.

Recently, while refactoring an older project at the new company, I noticed many places that did not use debounce/throttle for optimization. Using them again and again, I suddenly realized I was not actually that clear on the difference between the two. So this post is a way to walk myself through what each one does and the common scenarios where they are used.

throttle

The official definition is that throttle makes a function execute only once within a given period of time, and it executes continuously. Common scenarios include window scroll and window resize, basically continuous events. The main goal is to avoid stack overflow caused by scroll/resize firing too frequently.

throttle demo:

funtion throttle( targetFunc, limitPeriod ){
	let inThrottle;
	
	return function()=>{
		const args = arguments;
		const context = this;
		if (!isThrottle) {
		      targetFunc.apply(context, args);
		      inThrottle = true;
		      setTimeout(() => inThrottle = false, limit);
		  }
	}
}

throttle demo with arrow function

funtion throttle( targetFunc, limitPeriod ){
	let inThrottle;
	return (...args)=>{
		if (!inThrottle) {
		      targetFunc(...args);
		      inThrottle = true;
		      setTimeout(() => inThrottle = false, limit);
		  }
	}
}

Debounce

For debounce, the function is only executed after a period of time has passed, with the goal of capturing the last triggered event. Common scenarios are running a function from input changes or submitting a form. Window scroll/resize can also use debounce, but the goal there is to run the target event only after scroll/resize has stopped for a while.

debounce demo

function debounce( targetFunc, delayPeriod ){
	let inDebounce;
	return function(){
		const args = arguments;
		const context = this;
		clearTimeout(inDebounce);
		inDebounce = setTimeout(() => targetFunc.apply(context, args), delayPeriod);
	}
}

debounce demo with arrow function

function debounce( targetFunc, delayPeriod ){
	let inDebounce;
	return (...args)=>{
		clearTimeout(inDebounce);
		inDebounce = setTimeout(() => targetFunc( ...args), delayPeriod);
	}
}

Ref

  • lodash document: link

ChangeLog

  • 20230627: init
  • 20260501–translate by claude code