React-Query能否实现串行网络请求并等待前一个请求完成?
解决React-Query请求串行化的问题
要处理这个API限流的问题,你可以给React-Query添加串行请求控制逻辑,让请求一个接一个发起,避免同时触发多个请求导致429错误。下面提供两种可行的修改方式:
方式一:全局串行请求队列(适合全应用复用)
先创建一个全局的请求队列工具,把每个请求都加入队列,确保前一个请求完成后再执行下一个:
// 全局维护一个串行请求的Promise链 let requestQueue = Promise.resolve(); // 包装串行请求的工具函数 const serialFetch = (fetchFn) => { // 把当前请求加入队列,前一个完成后再执行 requestQueue = requestQueue .then(() => fetchFn()) .catch(() => fetchFn()); // 失败后也继续执行下一个请求,可根据需求调整 return requestQueue; };
然后修改组件中的useQueries配置,用serialFetch包装你的请求函数:
const [selection, setSelection] = React.useState([]); const results = useQueries( selection.map(item => ({ queryKey: ['something', item], queryFn: () => serialFetch(() => fetchItem(item)), // 可选:设置重试次数,重试也会遵循串行规则 retry: 2 })) ); const data = results.map(result => result.data);
这种方式会让所有通过serialFetch包装的请求严格按顺序执行,同一时间只有一个请求在调用目标API。
方式二:组件内本地控制串行请求(适合单组件场景)
如果只需要在当前组件实现串行请求,可以用useRef维护请求进度,结合useEffect逐个触发请求:
import { useQueryClient } from '@tanstack/react-query'; const [selection, setSelection] = React.useState([]); const [queryResults, setQueryResults] = React.useState([]); const queryClient = useQueryClient(); // 记录当前处理到第几个请求 const currentIndexRef = React.useRef(0); React.useEffect(() => { if (selection.length === 0) { setQueryResults([]); currentIndexRef.current = 0; return; } const fetchNext = async () => { if (currentIndexRef.current >= selection.length) return; const item = selection[currentIndexRef.current]; try { // 用queryClient手动发起请求,保留React-Query的缓存能力 const data = await queryClient.fetchQuery({ queryKey: ['something', item], queryFn: () => fetchItem(item) }); setQueryResults(prev => [...prev, { data }]); } catch (err) { setQueryResults(prev => [...prev, { error: err }]); } finally { // 处理完当前请求,继续下一个 currentIndexRef.current += 1; fetchNext(); } }; // 重置状态,开始执行第一个请求 setQueryResults([]); currentIndexRef.current = 0; fetchNext(); // 清理函数:如果组件卸载或selection变化,终止当前请求 return () => { currentIndexRef.current = selection.length; }; }, [selection, queryClient]); // 最终数据结构和原代码一致 const data = queryResults.map(result => result.data);
这种方式在组件内部手动控制请求顺序,同时保留了React-Query的缓存功能,不会浪费缓存优势。
内容的提问来源于stack exchange,提问作者SpaceOso
相关产品推荐
相关产品推荐

