JS函数节流(throttle)与函数去抖(debounce)

dhso
2017/11/15 13:59
统计中

在浏览器中,往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃。相关事件如 resize , scroll , mousemove 等。在实际场景中,需求大多为停止改变大小n毫秒后执行后续处理或者是以一定的频率执行后续处理。针对这两种需求就出现了 debouncethrottle 两种解决办法。

throttle 节流

如果将水龙头拧紧直到水是以水滴的形式流出,那你会发现每隔一段时间,就会有一滴水流出。

也就是会说预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。

实现代码

function(func, wait, options) {
		var timeout, context, args, result;
		var previous = 0;
		if (!options) options = {};
		var later = function() {
			previous = options.leading === false ? 0 : new Date().getTime();
			timeout = null;
			result = func.apply(context, args);
			if (!timeout) context = args = null;
		};
		var throttled = function() {
			var now = new Date().getTime();
			if (!previous && options.leading === false) previous = now;
			var remaining = wait - (now - previous);
			context = this;
			args = arguments;
			if (remaining <= 0 || remaining > wait) {
				if (timeout) {
					clearTimeout(timeout);
					timeout = null;
				}
				previous = now;
				result = func.apply(context, args);
				if (!timeout) context = args = null;
			} else if (!timeout && options.trailing !== false) {
				timeout = setTimeout(later, remaining);
			}
			return result;
		};
		throttled.cancel = function() {
			clearTimeout(timeout);
			previous = 0;
			timeout = context = args = null;
		};
		return throttled;
	}

使用代码

tag.onmousemoveApplet = app.throttle(function() {
  console.log('1s内响应一次!');
		}, 1000);

debounce 去抖

如果用手指一直按住一个弹簧,它将不会弹起直到你松手为止。

也就是说当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

实现代码

function(func, wait, immediate) {
		var timeout, result;
		var later = function(context, args) {
			timeout = null;
			if (args) result = func.apply(context, args);
		};
		var debounced = restArgs(function(args) {
			if (timeout) clearTimeout(timeout);
			if (immediate) {
				var callNow = !timeout;
				timeout = setTimeout(later, wait);
				if (callNow) result = func.apply(this, args);
			} else {
				timeout = _.delay(later, wait, this, args);
			}

			return result;
		});
		debounced.cancel = function() {
			clearTimeout(timeout);
			timeout = null;
		};

		return debounced;
	}

使用代码

tag.onmousemoveApplet = app.throttle(function() {
  console.log('停下1s后响应一次!');
		}, 1000);

本文为 dhso 原创

发布在 http://blog.minws.com/jshan-shu-jie-liu-throttle-yu-han-shu-qu-dou-debounce/

如有转载,请标明来源!

作者信息
姓名:dhso
热评文章
最新评论
文章概览