如何在 GraphQL 中使用订阅查询缓存更新

在前端开发中,GraphQL 已经成为了越来越受欢迎的 API 查询方式。而对于实时性和实时更新的需求,订阅查询(Subscription)是 GraphQL 中非常重要的一个概念。在订阅查询中,客户端可以订阅服务端某个数据源的变化,并在数据源发出变化时,实时接收到更新。但是,如何在 GraphQL 中使用订阅查询缓存更新却是一个不太容易解决的问题。本文将介绍如何在 GraphQL 中使用订阅查询缓存更新,以及相关示例代码。

使用订阅查询更新缓存的挑战

GraphQL 中的缓存机制本质上是使用了 Apollo Client 的缓存,减少数据的重复获取,加快网络请求的速度。但是,GraphQL 的订阅查询并没有直接的缓存机制。换句话说,一旦某个查询结果发生变化,我们就能接收到对应的订阅,但是如何在客户端中更新缓存?这是一个非常关键的问题。

这涉及到 GraphQL 缓存的工作原理,以及如何将订阅接收到的信息与缓存处理进行整合。在使用订阅查询更新缓存时,需要明确以下两个问题:

  • 如何保存订阅所接收到的数据?
  • 如何更新与订阅相关的缓存?

实际上,我们需要利用 Apollo Client 中提供的缓存 API 和 Subscription API,进行相关的操作。

订阅查询缓存的实现

假设我们有如下的查询和订阅定义:

----- ---------------- ---- -
  ------------ -------- -
    --
    ----
  -
-

------------ -------------------- ---- -
  ------------------- -------- -
    --
    ----
  -
-
  • getUser 用于查询指定用户 ID 的用户信息。
  • userUpdated 用于订阅用户信息的更新。

接下来,我们将使用 React 和 Apollo Client 将这两个查询和订阅整合在一起。

使用 useSubscription 处理订阅

使用 useSubscription 可以让订阅变得非常简单。这是一个 React 专用钩子(Hook),允许我们通过在组件中定义订阅,将订阅结果与组件状态关联起来。以我们的例子为例,可以按照以下方式实现 useSubscription

----- - ---- - - ----------------
  --------------------------
  - ---------- - ------ - -
--

useSubscription 接收两个参数:

  • 订阅查询,也就是 userUpdated
  • 订阅的参数,也就是 userId

如果我们的订阅查询返回了更新后的用户信息,这个数据将被自动更新到 data 变量中。

使用 useQuery 处理查询

使用 useQuery 类似于 useSubscription,只不过它用于处理查询。以我们的例子为例,可以按照以下方式实现 useQuery

----- - ----- -------- ----- - - ------------------ -
  ---------- - ------ -
---

如上所述,useQuery 用于从 GraphQL 服务器获取数据,其中 GET_USER 是查询定义, userId 是查询的参数。请求完成后,useQuery 将返回查询结果。

更新缓存数据

有了 useSubscriptionuseQuery,我们可以订阅查询的结果,并获取已有的查询结果。接下来的问题是如何将新的查询结果插入到客户端缓存中,以更新缓存数据。

在 React 中使用 useMutation 钩子,可以将一个函数赋值给一个变量,这个函数可以在 Apollo Client 的缓存中更新数据:

----- ------------ - -------------------------

------------
  ---------- - ------ --
  ------- ----- -- -
    ------------------
      ------ ---------
      ---------- - ------ --
      ----- - ----- --------------- -
    ---
  -
---

在这个例子中,我们可以调用 updateUser 并将新获取到的用户信息更新到缓存中。其中 writeQuery 函数接收三个参数:

  1. 查询定义,即 GET_USER
  2. 查询的参数,即 userId
  3. 新的数据更新,即 updatedUserData

完整代码示例

最后,我们使用上述技巧构建一个完整的代码示例:

------ ----- ---- --------
------ - ---------------- --------- ----------- - ---- -----------------

----- ------------------------- - ----
  ------------ -------------------- ---- -
    ------------------- -------- -
      --
      ----
    -
  -
--

----- -------- - ----
  ----- ---------------- ---- -
    ------------ -------- -
      --
      ----
    -
  -
--

----- ----------- - ----
  -------- ------------------- ---- ------ -------- -
    ------------------ -------- ----- ------ -
      --
      ----
    -
  -
--

-------- ------ ------ -- -
  ----- - ----- -------- ----- - - ------------------ -
    ---------- - ------ -
  ---

  ----- - ----- ----------- - - ------------------------------------------ -
    ---------- - ------ -
  ---

  ----- ------------ - -------------------------

  ----- ------------ - -- -- -
    ----- --------------- - - --- ------- ----- --------- --
    ------------
      ---------- - ------- ------------------ -
      ------- ----- -- -
        ------------------
          ------ ---------
          ---------- - ------ --
          ----- - ----- --------------- -
        ---
      -
    ---
  --

  ------ -
    -----
      -------- -- ------------------
      ------ -- ------------ ---- ------ --------------------
      --------- -- ---- -- -
        -----
          ------- --------------------
          ------- ----------------------------- -------------
        ------
      --
      ------------ -- -
        -----
          ------- ------------------------------ --- ---- -----------
        ------
      --
    ------
  --
-

在这个代码示例中,我们把 useSubscriptionuseQueryuseMutation 结合起来使用,通过订阅查询,在客户端缓存中更新数据。如果我们通过点击“更新名字”按钮来更新缓存,这里的代码将接收到一个订阅,将获取到更新后的用户信息,然后通过 cache.writeQuery 将新的数据更新到客户端缓存中。

结论

使用订阅查询更新缓存在 GraphQL 中是一个非常复杂的问题,但我们可以通过合理使用 Apollo Client 中提供的缓存 API 和 Subscription API,加深对 GraphQL 的理解,并间接提高自己的 React 和 Apollo Client 使用技能。

在开发过程中,我们要注重细节,并且确保在更新缓存时,数据能够及时地更新到客户端。总体来说,使用订阅查询更新缓存是 GraphQL 开发中的一个重要技能,希望这篇文章能够帮助你更好地理解 GraphQL 的本质和机制,提高自己的开发效率。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/67370de6317fbffedf07b7fe