简介
现代 Web 应用程序需要高效、灵活的数据获取。 GraphQL 是一种彻底改变 API 开发的查询语言,可以满足这一需求。自 Facebook 2015 年首次亮相以来,GraphQL 的广泛采用证明了其价值超越了转瞬即逝的趋势。
理解 GraphQL 的核心原则
GraphQL 是一种 API 查询语言和运行时。与服务器决定响应结构的传统 REST API 不同,GraphQL 允许客户端通过单个请求请求精确的数据。这解决了许多现代应用程序开发挑战。
想象一下一位知识渊博的图书管理员可以快速找到任何一本书。您无需搜索多个书架(多个 API 端点),只需提供详细的请求,图书馆员就会返回您所需要的内容 — 不多也不少。
GraphQL 的模式驱动性质创建了清晰的客户端-服务器契约。 每个 GraphQL 服务都定义数据类型,从而在执行之前启用模式验证,以获得可预测的一致响应。
技术基础
GraphQL 使用三个主要操作:查询(数据检索)、突变(数据修改)和订阅(实时更新)。 强大的类型系统支持每个操作,定义 API 功能。
<code>type User { id: ID! name: String! email: String! posts: [Post!]! friends: [User!]! } type Post { id: ID! title: String! content: String! author: User! comments: [Comment!]! createdAt: String! } type Comment { id: ID! text: String! author: User! post: Post! }</code>
架构定义关系,允许在单个查询中进行嵌套数据检索(例如,用户的帖子或朋友)。
解析器:GraphQL 的核心
GraphQL 的强大之处在于它的解析器函数。这些函数检索每个架构字段的数据。 解析器可以从数据库获取数据、调用其他 API 或执行复杂的计算,所有这些对客户端都是透明的。
解析器示例(使用 Prisma)
以下是如何使用 Prisma 实现解析器来获取用户的帖子和好友:
<code>const resolvers = { User: { async posts(parent, args, context) { const posts = await context.prisma.post.findMany({ where: { authorId: parent.id }, orderBy: { createdAt: 'desc' }, }); return posts; }, async friends(parent, args, context) { const friends = await context.prisma.user.findMany({ where: { id: { in: parent.friendIds }, }, }); return friends; }, }, };</code>
这些解析器仅在请求时有效地获取数据。
API 开发的演变
还记得纯 REST API 的日子吗?多个端点返回固定的数据结构。 这适用于简单的应用程序,但随着复杂性的增加而变得笨拙。移动和 Web 客户端需要不同的数据,导致多次 API 调用。
解决 N 1 查询问题
N 1 查询问题(通过多个数据库查询获取相关数据)是一个重大的 API 挑战。 GraphQL 使用 DataLoader 和类似工具批量和优化查询的能力改变了性能。
实现示例(DataLoader):
获取相关数据常常会导致N 1 问题。 GraphQL 通过 DataLoader、批处理和缓存数据库调用等工具解决了这个问题:
<code>type User { id: ID! name: String! email: String! posts: [Post!]! friends: [User!]! } type Post { id: ID! title: String! content: String! author: User! comments: [Comment!]! createdAt: String! } type Comment { id: ID! text: String! author: User! post: Post! }</code>
这可以通过批处理请求最大限度地减少数据库查询,从而显着提高性能。
真实世界的成功故事
使用 Node.js 和 Apollo Server 实现 GraphQL
这是一个实际的实现:
安装依赖项:npm install @apollo/server graphql
定义您的架构:
<code>const resolvers = { User: { async posts(parent, args, context) { const posts = await context.prisma.post.findMany({ where: { authorId: parent.id }, orderBy: { createdAt: 'desc' }, }); return posts; }, async friends(parent, args, context) { const friends = await context.prisma.user.findMany({ where: { id: { in: parent.friendIds }, }, }); return friends; }, }, };</code>
<code>const DataLoader = require('dataloader'); const userLoader = new DataLoader(async (userIds) => { const users = await prisma.user.findMany({ where: { id: { in: userIds }, }, }); return userIds.map(id => users.find(user => user.id === id)); }); const resolvers = { Post: { async author(parent) { return userLoader.load(parent.authorId); }, }, };</code>
<code>const typeDefs = `#graphql type Query { hello: String }`;</code>
通过字段选择进行性能优化 (Prisma)
GraphQL 根据请求字段优化数据库查询:
<code>const resolvers = { Query: { hello: () => "Hello, GraphQL!", }, };</code>
这仅检索必要的数据,从而减少开销。
GraphQL 的未来
graphql-subscriptions
的示例:<code>const { ApolloServer } = require('@apollo/server'); const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`? Server ready at ${url}`); });</code>
GraphQL 入门
GraphQL 的逐步采用是一个关键优势。 首先将其与现有 REST API 一起实现,也许作为代理层。这可以在实现优势的同时最大限度地降低风险。
结论
GraphQL 是数据获取和客户端-服务器通信方面的范式转变。随着应用程序的增长,其灵活性和效率变得越来越重要。 考虑使用 GraphQL 来提高性能、开发人员体验和用户满意度。从小实验开始,逐步扩大其用途。蓬勃发展的社区和生态系统现在是将 GraphQL 集成到您的开发堆栈中的理想时机。
参考文献
作者简介
Ivan Duarte 是一名自由后端开发人员,热衷于 Web 开发和人工智能。
订阅我们的时事通讯
直接在收件箱中阅读 ByteUp 的文章。立即订阅!
以上是GraphQL 转变 API 开发的详细内容。更多信息请关注PHP中文网其他相关文章!