其实,节流并不是一个高深的概念,它的目的是屏蔽掉一些无用或非必要的行为。本文从两个场景来介绍一下节流在前端开发中的应用
两个场景:
- 实时检索,需要随用户输入调取接口实时获取结果,特点是请求比较频繁,但无法保证响应触达前端的时序性
- 登录接口,请求成功后不允许再次请求。
实时检索
流程:输入关键字->触发检索接口调用->展示接口返回内容。
这里的问题在于接口返回的时序性,假设用户输入先后触发了三次请求并拿到结果:_a,_b,_c,然而阴差阳错导致接口响应触达前端的顺序是:_b->_c->_a,这里就需要做一些处理,来屏蔽掉不必要的展示(这里的_a就是无意义的了,因为_b已经到达前端了)。此时请求已经发出,需要对那些无意义的请求的数据返回做丢弃处理。
下面代码中,每次新请求发送之前先将上次发出的请求标记为过期状态,请求响应的回调里判断本次请求是否过期,过期则直接丢弃(return)
let lastRecord = null
const requestDispatcha = (keyword:string) => {
//标记之前的请求为过期
if(lastRecord){
lastRecord.outDated = true
}
const newRecord = lastRecord = {
request:fetch(keyword).then((data) => {
if(newRecord.outDated){
return;
}
//业务代码,展示搜索结果
...
}),
//标签
outDated:false
}
}
当然,根据需要还可以对接口调用做一些节流,这里不再赘述。
用户登录
流程:输入账户密码->点击登录按钮->调用接口->跳转到平台首页
此处用户点击按钮触发登录接口的调用,如果用户手快多点了几次,那么就会触发多次接口请求,因此我们需要设置一个变量记录登录接口调用状态:
const [loginAPICallStatus,setLoginAPICallStatus] = useState<'undefined'|'pending'|'rejected'|'success'>('undefined')
...
const handleLgnBtnClick = () => {
//请求控制
if(loginAPICallStatus === 'pending' || loginAPICallStatus === 'success'){
return;
}
setLoginAPICallStatus('pending')
//API requesting
loginAPIRequest(...).then(()=>{
//success
setLoginAPICallStatus('success')
},err=>{
//failure
setLoginAPICallStatus('rejected')
}).finally(()=>{
//重置变量
})
}
通过上面的代码,程序的稳定性有了显著的改善