[技術筆記]有關throttle和debounce的小梳理

常用,但又不甚了解的熟悉函數

Posted by 李定宇 on Tuesday, June 27, 2023

前端效能之防抖與節流

前言

遙想當年,第一次接觸防抖(debounce)與節流(throttle)時,想說這又是什麼奇怪的術語,為啥要把事情搞得那麼複雜?之後做一下簡單的搜尋,知道是用來提升效能、防止stack overflow的解決方案,而後就是遇到相似的feature、直接用lodash.debounce來應付應付。

不過,最近在翻修新公司的舊專案,發現很多地方都沒有利用debounce/throttle來優化,用著用著突然覺得自己對於兩者的分別其實也沒有到非常清楚,因此本篇文算是用來自我梳理一下,兩者的作用以及常見的使用場景。

throttle(節流)

官方說法是,throttle是讓一個函數在一段時間內只執行一次,而且它是連續執行的。常見的使用場景為 視窗scroll、視窗resize等連續事件,主要是避免 scroll/resize頻繁觸發而導致stack overflow

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(防抖)

對於debounce來說,它是在一段時間之後才執行該函數,目的是為了獲取最後一次觸發的事件。常見的使用場景為 input來執行函數、提交表單,而視窗的 scroll/resize時機也可以用debounce,不過目的是為了在 scroll/resize 停止一段時間後再執行目標事件。

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: 初稿