防抖与节流

392 阅读3分钟

防抖

  • 用户触发事件过于频繁,只要最后一次

用户输入内容,获取联想词。但是,每敲一个字就调用接口的话,因为频繁调用接口很浪费资源,所以我们在代码中使用防抖来解决这个问题,只有再用户输入完毕的一段时间后,才会调用接口,出现相对应的数据。

防抖1.gif
我们只是要拿到猪肉这个关键字然后调取接口去获取联想词,但是就如上面gif显示的一样,我们在输入的过程中就不断调取接口,这十分浪费资源,解决这个问题,我们要采取防抖措施。

	let t = null
	let inp = document.querySelector('input')
	inp.oninput = function () {
		if ( t != null ) {
			clearInterval(t)
		}
		t = setTimeout(() => {
			// 调取接口(需求)
			console.log(this.value)
		}, 500);
	}

我们引入一个标记t,用这个t来判断我们是否有输入完毕,这段代码的防抖措施就是类似我判断在0.5s内是否还有接着在input框输入,如果有就清除之前的定时器不调取接口,然后重新在生产一个定时器。如果超过0.5秒没有继续输入就认定为输入结束,可以调取接口。

不过呢,这样的话显然 防抖措施和业务所需要的调取接口都写在一起,不利于维护,所以我们简单的封装一下。

	let inp = document.querySelector('input')
	inp.oninput = debounce(function () {
                // 调取接口(需求)
		console.log(this.value)
	}, 500)
	function debounce(callback , delay) {
                // 闭包保存标记t
		let t = null
		return function () {
			if ( t != null) {
				clearInterval(t)
			}
			t = setTimeout(() => {
                                // 修改this指向,不然输出 undefined
				callback.call(this)
			}, delay);
		}
	}

防抖2.gif

节流

  • 控制高频事件执行次数,指定时间间隔内只会执行一次任务。

用户在阅读文章的时候,我们需要监听用户滚动到了哪个标题,但是每滚动一下就监听,那样会太过频繁从而占内存,如果再加上其他的业务代码,就卡住了

节流1.gif
我们和防抖一样,引入第三个变量flag,让事件在规定时间内指执行一次。下面的节流代码和上面的防抖代码其实是差不多的,这里就不做过多的讲解,直接看效果吧。

	let flag = true;
	window.onscroll = throttle(function () {
		console.log('调取接口')
	} , 500)

	function throttle(callback , delay) {
                // 闭包保存标记flag
		let flag = true
		return function () {
			if (flag) {
				setTimeout(() => {
					callback.call(this)
					flag = true
				}, delay);
			}
			flag = false
		}
	}

节流2.gif

应用场景

防抖:

  • 一些表单元素的校验
  • 部分搜索功能的联想结果实现

节流:

  • 用户点击提交按钮,假设我们知道接口大致的返回时间的情况下,我们使用节流,只允许一定时间内点击一次
  • scroll,resize, touchmove, mousemove等极易持续性促发事件的相关动画问题,使用节流按一定时间的频率获取

参考

2019 面试准备 - JS 防抖与节流
函数防抖和节流
如何全面出色的回答面试官防抖与节流提问?
up主-晓舟报告