目前小弟接手一个专案,前端Vue都是利用@tanstack/vue-query的套件来向后端发送API,只是这样要如何避免Server及Client端重复发送API?我有将问题丢给Copilot,他给出的解答如下:

Vue Query 的快取机制能有效避免伺服器和客户端重复呼叫 API,主要是通过以下几个方面来实现的:

  • 快取资料当你使用 useQuery 来获取资料时,Vue Query 会自动将返回的资料快取起来。这意味着在相同的查询键(queryKey)下,后续的查询会直接从快取中获取资料,而不是重新发送 API 请求1。

  • 资料过期时间(staleTime)你可以设定资料的过期时间(staleTime),在这段时间内,资料被认为是新鲜的,不会重新获取。这样可以避免在短时间内重复发送相同的 API 请求1。

  • const { data } = useQuery(\'todos\', fetchTodos, {staleTime: 1000 * 60 * 5, // 资料过期时间设为5分钟})3. 初始资料(initialData)在伺服器端渲染(SSR)中,你可以使用 initialData 来提供初始资料,这样客户端在初次渲染时就不需要再次发送 API 请求1。

    const { data } = useQuery(\'todos\', fetchTodos, {initialData: serverData, // 来自伺服器端的初始资料})4. 快取键(queryKey)每个查询都有一个唯一的快取键(queryKey),这个键用来标识和管理快取资料。当相同的快取键被使用时,Vue Query 会重用快取中的资料,而不是重新发送请求1。

  • 背景重新获取(Background Refetching)当资料过期或需要更新时,Vue Query 会在背景中自动重新获取资料,而不会影响使用者的体验。这样可以确保使用者看到的是最新的资料,同时避免不必要的重复请求1。
  • 综合范例以下是一个综合范例,展示如何利用 Vue Query 的快取机制来避免重复呼叫 API:

    import { useQuery } from \'@tanstack/vue-query\'

    export default {setup() {const { data, error, isLoading } = useQuery(\'todos\',() => fetch(\'/api/todos\').then(res => res.json()),{staleTime: 1000 * 60 * 5, // 资料过期时间设为5分钟initialData: serverData, // 来自伺服器端的初始资料})

    return { data, error, isLoading }

    }}在这个范例中,useQuery 会快取从 /api/todos 获取的资料,并在5分钟内重用这些资料,避免重复请求。同时,利用 initialData 提供伺服器端的初始资料,避免客户端初次渲染时重复发送 API 请求。

    然而,我看官网的快取范例说明(https://tanstack.com/query/latest/docs/framework/vue/guides/caching),似乎只有设定 staleTime (资料过期时间),在时间范围内前端才不会重复发送API请求。

    因此,到底是Vue Query本身的快取机制,还是只有staleTime,抑或是其他的机制可以避免Server及Client端重复发送API?

    1 个回答

    1

    呆呆小将

    iT邦新手 2 级 ‧ 2025-02-27 16:40:47

    看要不要检查一下,有时候是原先的工程师没有善用套件不是套件问题

    1. api useQuery 是否反覆被初始化,甚至你画面包含 api 整组被重新 render 出来那就会是整组新的
    2. 是否原先的使用者是无条件使用 refetch 呼叫,又或者只要打 api 就会先把 queryKey 更动,导致每次都会搜寻新的内容

    以上是前阵子初次用时踩的雷,搞不好会中,不然更多的就要看 Code 了


    • 1

    danny_tseng

    iT邦新手 5 级 ‧
    2025-03-03 11:40:25

    了解,所以只要api的queryKey没有更动,就不会重新发送api请求吗?

    修改