axios react-query可以进行连续的网络调用并等待前一个调用完成吗?

a9wyjsp7  于 2023-10-18  发布在  iOS
关注(0)|答案(2)|浏览(120)

例如,在下面的代码中,我如何更新react-query以等待上一个调用完成后再开始下一个调用?
我试图打一个API,有速率限制,一次一个调用,但我有一个列表,我需要做的调用,我得到一个429,如果一个以上的是在同一时间完成。

const [selection, setSelection] = React.useState([])

const results = useQueries(
  selection.map(item => ({
    queryKey: ['something', item]
    queryFn: () => fetchItem(item)
   })
)

const data = results.map(result => result.data)
velaa5lx

velaa5lx1#

我不知道有什么内置的解决方案。
但这个怎么样。对已运行的查询进行计数并启用下一个查询的状态。
您可能需要staleTime: Infinity来确保库不会同时重新获取所有查询。

const [selection, setSelection] = React.useState([])
const [noCompleted, setNoCompleted] = React.useState(0)

const results = useQueries(
  selection.map((item, i) => ({
    queryKey: ['something', item]
    queryFn: () => fetchItem(item)
    enabled: i <= noCompleted
    staleTime: Infinity
    cacheTime: Infinity
   })
)

const firstLoading = results.findIndex((r) => r.isLoading)

React.useEffect(() => {
  setNoCompleted(firstLoading)
}, [firstLoading])
knsnq2tg

knsnq2tg2#

正如Anton建议的那样,React Query exposes a method调用了enabled。为了向您说明,使用普通方法循环遍历您的项,然后仅在上一个查询完成时调用RQ,然后切换enabled状态。这是一个非常粗略的,更详细的例子,在这里运行replit。
我还在replit中包含了如何重用该高速缓存,因此请让我知道它是否有意义。它肯定可以优化得更好,setTimeout只是为了直观地向您展示进度。

async function getCoins(coin: string): Promise<APIResponse> {
  try {
    const response = await fetch(`https://api.gemini.com/v2/ticker/${coin}usd`);
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("There was a problem with the fetch operation:", error);
    throw error;
  }
}

export function useCoin(coins: string[]) {
  const [currentIndex, setCurrentIndex] = useState(0);
  const [allData, setAllData] = useState<APIResponse[]>([]);

  const query = useQuery(['coinData', coins[currentIndex]], () => getCoins(coins[currentIndex]), {
    enabled: currentIndex < coins.length,
    onSuccess: (data) => {
      setTimeout(() => {
        setAllData(prev => [...prev, data]);
        setCurrentIndex(prev => prev + 1);
      }, 1500)
    }
  });
  return { ...query, data: allData };
}

export function CachedEntries() {
  const [eth, setEth] = useState<APIResponse | null>(null)
  const cached = queryClient.getQueryData<APIResponse>(['coinData', 'eth'])

  useEffect(() => {
    if (cached) {
      setEth(cached);
    }
  }, [cached]);

  return eth !== null ? (
     <div>Entries from cache:
        <div key={eth?.symbol}>{eth?.symbol}: {eth?.close}</div>
      </div>
  ) : null
}

export function Entries() {
  const { data, error, isError } = useCoin(['btc', 'eth']);

  if (isError) console.log(error)

  return (
    <div>
      <div>Entries from query:
        <div>{data?.map(coin => (
          <div key={coin.symbol}>{coin.symbol}: {coin.close}</div>
        ))}</div>
      </div>
      <CachedEntries />
    </div>
  )
}

Anton的例子中,他使用了内置的useQueries,这是一种更好的方法。希望在这两个答案之间,你可以理解如何使用RQ,它是如何工作的,以及你可以用它做的很酷的事情。

相关问题