谈谈如何节流优化接口调用

508 阅读2分钟

其实,节流并不是一个高深的概念,它的目的是屏蔽掉一些无用或非必要的行为。本文从两个场景来介绍一下节流在前端开发中的应用

两个场景:

  • 实时检索,需要随用户输入调取接口实时获取结果,特点是请求比较频繁,但无法保证响应触达前端的时序性
  • 登录接口,请求成功后不允许再次请求。

实时检索

流程:输入关键字->触发检索接口调用->展示接口返回内容。

这里的问题在于接口返回的时序性,假设用户输入先后触发了三次请求并拿到结果:_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(()=>{
        //重置变量
    })
}

通过上面的代码,程序的稳定性有了显著的改善