React Native使用axios实现搜索时如何保证请求与响应顺序一致
问题解决方案
你遇到的是搜索场景典型的请求竞态问题,推荐优先使用AbortController终止过期请求的方案,不仅能解决结果错乱问题,还能减少无效网络消耗,是该场景的最优解法。
方案一:AbortController 终止过期请求(推荐)
核心逻辑:每次发起新的搜索请求前,终止上一次未完成的旧请求,旧请求被终止后不会触发后续的结果更新逻辑。
修改后的代码如下:
function Search (){ const [results, setResults] = useState([]); const [searchText, setSearchText] = useState(''); // 存储请求的取消控制器 const abortControllerRef = useRef(null); useEffect(() => { getSearchResultsDebounce(searchText); // 组件卸载时取消待执行的防抖函数和未完成的请求 return () => { getSearchResultsDebounce.cancel(); abortControllerRef.current?.abort(); } }, [searchText]); const getSearchResultsDebounce = useCallback( _.debounce(searchText => { // 发起新请求前,先取消上一次未完成的请求 abortControllerRef.current?.abort(); // 创建新的取消控制器 const newController = new AbortController(); abortControllerRef.current = newController; getSearchResults(searchText, newController.signal); }, 1000), [] ); function getSearchResults(searchText, signal) { const urlWithParams = getUrlWithParams(url, searchText); axios.get(urlWithParams, { headers: config.headers, // 传入signal关联请求和取消控制器 signal: signal }) .then(response => { if (response.status === 200 && response.data) { setResults(response.data); } else{ //Handle error } }) .catch(error => { // 忽略请求被取消的报错,不要当成异常处理 if (axios.isCancel(error)) return; // 其他错误正常处理 //Handle error }); } return ( <View> <SearchComponent onTextChange={setSearchText}/> <SearchResults results={results}/> </View> ) }
方案二:搜索词比对忽略过期响应(无取消请求需求时可选)
如果你的业务场景需要保留所有请求的响应结果,不需要取消请求,可以用比对当前返回结果对应搜索词和最新搜索词的方式,只更新最新搜索词对应的结果:
只需要新增搜索词ref并修改getSearchResults的逻辑即可:
function Search (){ const [results, setResults] = useState([]); const [searchText, setSearchText] = useState(''); // 存储最新的搜索词 const latestSearchTextRef = useRef(''); useEffect(() => { latestSearchTextRef.current = searchText; getSearchResultsDebounce(searchText); return () => { getSearchResultsDebounce.cancel(); } }, [searchText]); const getSearchResultsDebounce = useCallback( _.debounce(searchText => { getSearchResults(searchText) }, 1000), [] ); function getSearchResults(searchText) { const urlWithParams = getUrlWithParams(url, searchText); axios.get(urlWithParams, { headers: config.headers }) .then(response => { if (response.status === 200 && response.data) { // 只有返回结果对应的搜索词和当前最新搜索词一致时才更新状态 if(searchText === latestSearchTextRef.current) { setResults(response.data); } } else{ //Handle error } }) .catch(error => { //Handle error }); } return ( <View> <SearchComponent onTextChange={setSearchText}/> <SearchResults results={results}/> </View> ) }
两种方案都能完全解决请求返回顺序错乱导致的结果错误问题,优先选择方案一即可。
内容的提问来源于stack exchange,提问作者chathup1
相关产品推荐
相关产品推荐

