背景
业务开发中,经常遇到过请求竞态问题,一般发生于 Tab 切换,以及,分页切换,等,如果某个操作,造成了 a,b两次请求,但是实际网络场景,不一定, 按照实际的预想,可能先请求的,最后才返回,可能会造成,当前的状态错误
策略-取消旧请求
- 我在开发中,遇到这类情况,首先会把当前返回的数据和请求参数里面唯一项,进行绑定数据存储,这样首先保证了,你返回的数据,是否一致。
- 那对于一些不可避免的重复请求,或误操作呢可以去取消上一个旧的请求,可以利用axios 的取消 Axios.CancelToken 来进行取消,类似防抖的概念,
- 但是这个只是前端视角的取消,实际请求还是发出去了。
案例
以目前常见的 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');
}
};