节流: 在规定时间内,多次触发事件,但是只执行一次
场景:输入框搜索,地图渲染
优化用户体验
/** * 节流 规定时间内不管触发多少次只执行一次 * @param {Function} fn 实际要执行的业务逻辑函数 * @param {Number} duration 在规定时间段内,业务逻辑函数只能执行一次,单位毫秒 */ function throttle(fn, duration) { let prev = Date.now(), timerid = null return function() { let now = Date.now() let args = arguments clearTimeout(timerid) // 一定要提前清除定时器,因为可以 else 分支执行后,设置了一个定时器,如果第二次触发满足 if 条件,则总共会执行两次 if ((now - prev) >= duration) { // 到了预定时间,执行设定函数 fn.apply(this, args) prev = now } else { // 没到预定时机,但是事件被触发了,重新起一个定时器 timerid = setTimeout(() => { // 这里保证了最少执行一次,否则达不到 if 条件,函数一次都不会执行 prev = now fn.apply(this, args) }, duration) } } }
防抖:多次触发事件,以最后一次触发时机开始,延迟规定时间执行
场景:浏览器滚动时加载图片,点击提交按钮
优化性能
/** * 防抖 不管事件触发多少次,以最后一次触发时机为准,延迟设定时间执行 * @param {Function} fn 实际要执行的业务逻辑函数 * @param {Number} duration 在规定时间段后,业务逻辑函数开始执行,单位毫秒 */ function debounce(fn, duration) { let timerid = null return function() { clearTimeout(timerid) // 每次触发都需要清除定时器,并且重新起一个定时器 timerid = setTimeout(() => { fn.call(this, arguments) }, duration) } }
有时候节流和防抖可以交替使用,看业务需求,并不是那么死板