GraphQL 是一种用于 API 的新兴查询语言,它可以让开发者根据需求查询 API 提供的数据。在 GraphQL 中,查询是由客户端来指定的,而不是由服务端来决定的。这种查询的方式给开发者带来了很多便利,但同时也存在着一个问题,就是可能会导致无限递归。本文将会介绍如何避免这种情况的发生。
什么是无限递归
无限递归是指在 GraphQL 查询中,一个对象 A 包含另一个对象 B,而对象 B 又包含对象 A 的情况。假设我们有如下两个数据类型:
type User { name: String! friends: [User!]! } type Query { user(name: String!): User }
在这个例子中,User 对象包含了一个数组 friends,即表示该用户的好友列表。
现在,我们需要查询一个用户 Andy 的好友列表,我们可以使用如下的 GraphQL 查询:
-- -------------------- ---- ------- - ---------- ------- - ---- ------- - ---- ------- - ---- ------- - ---- --- - ---------------- - - - - -
我们可以发现,这个查询会一直往下查询好友列表的好友列表,直到出现调用栈溢出的错误。这就是无限递归问题。
如何避免无限递归
要避免无限递归问题的发生,我们需要在 GraphQL 查询中使用关键字 fragment
和 alias
。在这里,我们需要调整接口的定义,增加一个 friends 的参数,来控制好友列表的深度。新的接口定义如下:
type User { name: String! friends(depth: Int!): [User!]! } type Query { user(name: String!): User }
接下来,我们需要使用关键字 fragment
去定义一个可复用的查询片段。在这里,我们定义了一个名为 UserFragment
的片段,它用于查询一个用户的信息,包括名字和好友列表:
fragment UserFragment on User { name friends(depth: 0) { name } }
这个片段中,我们的好友列表深度为 0,表示只查询好友的名字,不再查询好友的好友列表。
最后,我们需要使用关键字 alias
来定义我们的查询,这样我们就可以在同一次查询中,分别查询哪些信息。这样,我们就能够在查询过程中插入一个用于控制查询深度的参数(depth)。下面是具体的查询语句和结果:
{ andy: user(name: "Andy") { ...UserFragment friends(depth: 1) { ...UserFragment } } }
在这个查询中,我们使用了 alias
andy
来为用户 Andy 命名,以供后续使用。我们还为 Andy 和 Andy 的好友列表使用了我们之前定义的 UserFragment
来查询,但是在查询好友列表时,我们传递了参数 depth
等于 1,表示只查询一级好友的信息。下面是我们可以得到的结果:
-- -------------------- ---- ------- - ------- - ------- ------- ---------- - - ------- -------- ---------- -- -- - ------- ---------- ---------- -- - - - -
在这个结果中,我们只查询了 Andy 的名字和直接好友的名字,因为我们只查询了一层好友列表。这就是我们想要的效果。
总结
避免无限递归是一个常见的任务,尤其是在 GraphQL 查询中。我们可以使用关键字 fragment
和 alias
来帮助我们解决问题。通过这种方式,我们可以在 GraphQL 查询中插入一个用于控制查询深度的参数,以避免无限递归。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64a2aa7d48841e9894f20c1a