一、防抖
了解防抖之前,我们先来了解函数抖动,那么什么是函数抖动呢?
简单的说函数抖动是:短时间内连续触发多次请求,返回的结果中只有一次是需要的数据,从而浪费了多次请求的结果,导致服务器压力和影响性能。为了避免服务器压力和影响性能,防抖是很有必要的。
1.什么是防抖:
在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时。
2.应用场景:
百度搜索框的提示、注册时校验用户是否被使用、点击按钮事件等。
3.模拟防抖场景:
下面模拟一个输入框输入字符,根据输入的字符进行接口调用。
通过以上的图片没有做防抖的输入框每次输入一个字符就会触发一次控制台的日志打印,同理就会请求一次接口,那么多个字符就会触发多次接口,显然就会导致接口的浪费。
而做了防抖的输入框可以看出控制台打印的日志次数明显减少,显然可以减少接口多次请求,避免接口的浪费。
4.防抖的解决思路:
我们可以做一个定时器timer,500ms执行一次,当用户输入字符不超过500ms时都会清除当前的 timer 然后重新设置超时调用,即重新计时,同时接口也不会被触发;直到用户停止输入字符超过500ms后再进行调用接口,这样就会减少了多次调用接口,避免了服务器请求次数过多而导致服务器请求超时。
以下是防抖代码:
import React from 'react'; import { Layout, Form, Input } from 'antd'; const { Header, Footer, Content } = Layout; import styles from './index.less'; let timer: NodeJS.Timeout | null = null; const IndexPage = () => { // 没有做防抖 const unUseAntiShake = (e: any): void => { console.log('没有做防抖:', e.target.value) // 执行接口请求 } // 做了防抖 const UseAntiShake = (e: any): void => { clearInterval(timer) timer = setInterval(() => { clearInterval(timer) console.log('使用防抖后:', e.target.value) // 执行接口请求 },500) } return ( <Layout> <Header>Header</Header> <Content className={styles.content}> <Form name="basic" wrapperCol={{ span: 16 }} initialValues={{ remember: true }} autoComplete="off" style={{ width: 400, margin: '20px auto' }} > <Form.Item label="没有做防抖:" name="a" > <Input onChange={unUseAntiShake} /> </Form.Item> <Form.Item label="使用防抖后" name="b" > <Input onChange={UseAntiShake} /> </Form.Item> </Form> </Content> <Footer>Footer</Footer> </Layout> ); } export default IndexPage
二、节流
1.什么是节流
节流是规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流与防抖最大的区别就是,无论事件触发多么频繁,都可以保证在规定时间内可以执行一次执行函数。
2.节流的应用场景
点击事件、页面滚动加载等
3.节流的方法
时间戳、定时器等
4.模拟节流案例
下面进行点击事件进行模拟节流前后对比。
通过以上的图片可以看出,没有做节流前连续多次点击按钮控制台每次都会进行日志打印;而做了节流后连续多次点击按钮只会在规定的时间内触发一次日志打印,减少了多次控制台打印日志的次数。
5.节流的思路
方案一、时间戳进行节流,通过当前时间减去旧的记录时间大于规定的单位时间后才执行一次函数,每次执行函数后重置旧的时间为当前时间。
方案二、定时器进行节流,每隔一段时间就触发一次,当多次点击时对函数进行限制,只允许在规定的时间内触发。
以下是节流的代码
import React, { useState } from 'react'; import { Layout, Form, Input, Button } from 'antd'; const { Header, Footer, Content } = Layout; import styles from './index.less'; const IndexPage = () => { const [oldTime, setOldTime] = useState(0)// 旧的时间 const [flag, setFlag] = useState(true) // 没有做节流 const unUseThrottle = (e: any): void => { console.log('没有做节流', e) // 执行接口请求 } // 做了时间戳节流后 const useThrottle = (e: any): void => { let nowTime = new Date().getTime(); if (nowTime - oldTime > 500) { console.log('做了时间戳节流后', e) setOldTime(nowTime) } } // 做了定时器节流后 const useThrottleTime = (e: any): void => { if (flag) { setTimeout(() => { //到规定时间后执行函数,同时 flag = true; console.log('做了定时器节流后', e) setFlag(true) }, 500); } // flag = false;防止一直执行 setFlag(false) } return ( <Layout> <Header>Header</Header> <Content className={styles.content}> <div style={{ width: 200, margin: '30px auto' }}> <Button onClick={unUseThrottle}>节流前点击</Button> <Button onClick={useThrottle} style={{ margin: '20px 0' }}>做了时间戳节流后</Button> <Button onClick={useThrottleTime}>做了定时器节流后</Button> </div> </Content> <Footer>Footer</Footer> </Layout> ); } export default IndexPage
三、总结
防抖和节流各有各的特点与实现方法,防抖和节流的原理搞清楚了,我们可以根据需求调整防抖和节流的方法。