react-请求竞态问题

4 阅读1分钟

背景

业务开发中,经常遇到过请求竞态问题,一般发生于 Tab 切换,以及,分页切换,等,如果某个操作,造成了 a,b两次请求,但是实际网络场景,不一定, 按照实际的预想,可能先请求的,最后才返回,可能会造成,当前的状态错误

策略-取消旧请求

  1. 我在开发中,遇到这类情况,首先会把当前返回的数据和请求参数里面唯一项,进行绑定数据存储,这样首先保证了,你返回的数据,是否一致。
  2. 那对于一些不可避免的重复请求,或误操作呢可以去取消上一个旧的请求,可以利用axios 的取消 Axios.CancelToken 来进行取消,类似防抖的概念,
  3. 但是这个只是前端视角的取消,实际请求还是发出去了。

案例

以目前常见的 axios 举例子,请求之前看看有没有旧的重复请求,有则取消,组件卸载时也取消请求,通过取消请求来解决,实测,能规避掉因竞态问题导致的数据状态错误渲染问题

const getVolatility = (params,cancelToken) =>{
 request.post('/xxx', params, {
    cancelToken: cancelToken ? cancelToken.token : null
  });
}


if (cancelTokenSource.current) {
            cancelTokenSource.current.cancel('Operation canceled due to new request');
        }
        cancelTokenSource.current = Axios.CancelToken.source();
        const setVolatility = async () => {
            const requestParams = {
                calTime,
                volatilityType,
                varietyType,
                calType,
                endTradeDateType,
                exChangeCode,
                dateScope: params.dateScope,
                windCode: windCode,
                otc
            }

            if (calTime && varietyType?.windCodes === windCode) {
                    const res = await getVolatility(requestParams, cancelTokenSource.current)
                    setvalatilityData({
                        data: res,
                        underlying: windCode,
                        volatilityType: varietyType?.VarietyTypes === 10002 ? (params.volatilityType) : (isEndWithIR ? 0 : params.volatilityType),
                        endTradeDateType: otc === 1 ? 1 : params.endTradeDateType,
                        calTime

                    })

             
            }

        }

        setVolatility()

        return () => {
            // 组件卸载时取消请求
            if (cancelTokenSource.current) {
                cancelTokenSource.current.cancel('Component unmounted');
            }
        };