Skip to main content

GraphQL 面试

1. 什么是 GraphQL?它与 REST API 有什么区别?

GraphQL 是一个数据查询和操作语言,以及一个使用类型系统来执行查询的服务器端运行时。GraphQL 允许客户端请求它们需要的确切数据,不多也不少。与 REST API 相比,GraphQL 的优势在于:

  • 请求效率:客户端可以从多个资源获取数据,只用一次请求,减少了数据的过载和网络延迟。
  • 灵活性:客户端可以精确控制其需要的数据结构,使得前后端开发更加独立。
  • 更好的性能管理:由于减少了数据的冗余和请求次数,整体性能得到了提升。
  • 类型系统:GraphQL 的类型系统提供了 API 的结构描述,使得 API 更加易于理解和使用。

2. GraphQL 中的查询(Query)和突变(Mutation)有何不同?

  • 查询:用于获取数据。它们是只读的,不应该改变服务器上的数据。
  • 突变:用于修改数据。突变是写操作,如添加、更新或删除数据。在 GraphQL 中,突变通常需要更明确的处理,以确保数据的一致性和正确性。

3. 解释 GraphQL 中的“模式”(Schema)和“解析器”(Resolver)。

  • 模式:定义了在 GraphQL API 中可查询的所有类型和每种类型上的操作(如查询和突变)。模式是类型系统的核心,它定义了如何通过 GraphQL 访问数据。
  • 解析器:是连接 GraphQL API 字段和数据源的函数。每个字段在模式中都有相应的解析器,当该字段被查询时,解析器负责返回正确的数据。

4. 什么是内联片段(Inline Fragment)?在什么情况下需要使用它?

内联片段用于在一个查询内部对返回类型进行条件处理,尤其是当类型为联合或接口时。如果要根据对象的实际类型请求特定字段,就需要使用内联片段。例如,在处理不同类型的搜索结果时,可能需要对每种类型返回不同的字段。

这里的 ... on TypeName 就是内联片段。

{
search(query: "GraphQL") {
... on Article {
title
publishDate
body
}
... on Video {
title
publishDate
videoUrl
}
... on Podcast {
title
publishDate
audioUrl
}
}
}

5. GraphQL 如何处理错误?

GraphQL API 在执行查询时,如果遇到错误,会在响应中返回一个 errors 数组。每个错误都会详细描述问题所在,但不会中断整个查询的执行。这意味着即使某些字段因错误而无法解析,其他字段仍然可以成功返回数据。

6. GraphQL 的性能优化策略有哪些?

  • 查询批处理:减少到数据库或其他数据源的请求次数。
  • 缓存:使用服务器端或客户端缓存来存储已经请求过的数据,减少不必要的重复数据加载。
  • 查询优化:使用工具分析和优化复杂的查询,例如通过限制查询深度来防止过度的数据加载。
  • 持久化查询:将常用的查询存储在服务器上,客户端只需发送查询的标识符即可。

7. 问题:解释 GraphQL 的分页处理方式。

GraphQL 中常见的分页技术包括偏移量分页(Offset Pagination)和游标分页(Cursor-based Pagination)。偏移量分页通过指定起始点(偏移量)和数量来检索数据。游标分页则使用持续的标识(游标),来安全地遍历数据,特别适用于大数据量和实时更新的数据集。

8. 如何在 GraphQL 中处理授权和认证?

认证(Authentication)通常在 GraphQL 服务器接收到请求时处理,可以通过 HTTP 头部中的令牌来实现。授权(Authorization)则在解析器层面处理,确保用户只能访问他们有权访问的数据。这通常涉及到检查用户权限,然后根据权限来返回相应的数据或错误信息。

9. GraphQL 订阅是什么?它们是如何工作的?

GraphQL 订阅是一种让客户端实时接收数据更新的机制。与查询和突变不同,订阅通过持久连接(通常是 WebSocket)实现。当订阅的数据发生变化时,服务器会推送更新到所有订阅了该数据的客户端。

10. 你如何在设计 GraphQL 模式时考虑前向兼容性?

为了确保前向兼容性,应避免在现有字段上进行破坏性的变更(如更改字段类型或删除字段)。添加新的字段通常是安全的。此外,可以使用版本控制或者通过增加新的操作和类型来引入改变,而不是修改现有的定义。

11. 在 GraphQL 中,N+1 查询问题是什么?如何解决它?

N+1 查询问题发生在解析器为每个返回的对象分别发起一个新的数据库查询时。例如,如果客户端请求一个列表的用户以及他们的每一个朋友,服务器可能会首先查询用户列表,然后为列表中的每一个用户查询其朋友,导致大量的数据库请求。解决这个问题的方法包括使用 DataLoader 等工具来批处理和缓存这些请求,从而减少数据库的访问次数。