如何将 REST API 转换为 GraphQL API
REST API 和 GraphQL API 都是常见的前端开发中用来交换数据的方式,但是它们有着不同的设计理念和实现方式。REST API 设计的重点在于资源,每个资源都有一个固定的 URL,由 HTTP 动词来表示对该资源执行的操作。而 GraphQL API 则强调查询和变更的灵活性,客户端可以自由地定义需要获取的数据和变更的操作。在一些特定的场景下,REST API 可能会变得复杂难以维护,这时候将其转换为 GraphQL API 可能是一个不错的解决方案。本文将介绍如何将一个已有的 REST API 转换为 GraphQL API,并提供一些实用的指导意义和示例代码。
- 准备工作
在开始将 REST API 转换为 GraphQL API 之前,需要先明确一些重要的概念和工具。
GraphQL 是一种基于类型系统的查询语言和服务端运行时,可以用来描述 API 的类型和查询方式。GraphQL 支持查询、变更和订阅等多种操作。
GraphQL Schema 是定义 GraphQL API 的核心部分,它描述了所有可查询或可变更的类型、字段和操作。Schema 是由类型和字段组成的树形结构。
GraphQL Resolver 负责将 GraphQL 查询或变更映射到具体的请求和响应。Resolver 是一个函数,根据传入的查询参数和上下文,返回一个符合查询结果的值。
GraphQL Playground 是一个强大的 UI 工具,可以帮助我们快速构建 GraphQL API 和测试查询和变更操作。
GraphQL Yoga 是一个基于 Express 和 graphql-js 的 GraphQL 服务器,用于快速构建 GraphQL API。
- 初步设计
在将 REST API 转换为 GraphQL API 之前,我们需要先对 API 进行设计,并尽量遵循 GraphQL 的哲学和原则。首先需要定义 GraphQL Schema,并根据 REST API 的结构按照 GraphQL 类型来进行映射。例如,对于一个 Blog API,可以定义如下 Schema:
// javascriptcn.com 代码示例 type Author { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: Author! comments: [Comment!]! } type Comment { id: ID! content: String! author: Author! post: Post! } type Query { post(id: ID!): Post posts: [Post!]! author(id: ID!): Author authors: [Author!]! } type Mutation { createPost(title: String!, content: String!, authorId: ID!): Post! updatePost(id: ID!, title: String, content: String): Post! deletePost(id: ID!): ID! createComment(content: String!, authorId: ID!, postId: ID!): Comment! updateComment(id: ID!, content: String): Comment! deleteComment(id: ID!): ID! }
其中,Author、Post 和 Comment 分别代表了 Blog API 中的作者、文章和评论,每个类型中定义了对应的字段和 GraphQL 类型。Query 中定义了可查询的操作,如获取单篇文章、获取所有文章列表、获取单个作者、获取所有作者列表等。Mutation 中定义了可变更的操作,如创建一篇新文章、更新一篇已有文章、删除一篇文章等。需要注意的是,每个操作的返回值都应该是一个符合定义的类型,如上述 createPost 返回的是 Post 类型,deletePost 返回的是 ID。这样定义 Schema 可以有效地遵循 GraphQL 的设计原则,将 API 中的资源和操作转换为 GraphQL 类型和操作,并将查询与变更分离。
- 映射资源
定义好了 Schema 之后,我们需要将 REST API 中的资源映射到 Schema 中的类型。例如,对于 Blog API 中的文章,可以如下定义 Resolver:
// javascriptcn.com 代码示例 const resolvers = { Post: { author: async (parent, args, context) => { const author = await fetchAuthorById(parent.authorId) return author }, comments: async (parent, args, context) => { const comments = await fetchCommentsByPostId(parent.id) return comments }, }, Query: { post: async (parent, { id }, context) => { const post = await fetchPostById(id) return post }, posts: async (parent, args, context) => { const posts = await fetchAllPosts() return posts }, }, Mutation: { createPost: async (parent, { title, content, authorId }, context) => { const post = await createNewPost(title, content, authorId) return post }, updatePost: async (parent, { id, title, content }, context) => { const post = await updatePostById(id, { title, content }) return post }, deletePost: async (parent, { id }, context) => { const postId = await deletePostById(id) return postId }, }, }
其中,resolvers 对象包含了每个类型和操作对应的 Resolver 函数。对于 Post 类型中的 author 和 comments 字段,我们需要在 Resolver 中根据对应的 ID 或条件获取对应的资源。对于 Query 和 Mutation 中的操作,我们需要根据输入参数和对应的操作,调用 REST API 从服务器中获取或变更资源。在 Resolver 中,我们可以方便地使用 JavaScript 进行异步操作和调用其他模块。例如,在 createPost Resolver 中,我们可以通过调用 createNewPost 函数来创建一篇新文章,并将其返回。
- 使用 GraphQL Yoga 搭建服务器
经过上述的设计和映射,我们已经拥有了一个符合 GraphQL 标准的 API,接下来,我们需要将其部署到服务器上并进行测试。这里我们使用 GraphQL Yoga 搭建 GraphQL 服务器,它提供了用于创建 GraphQL API 的基础模板,并集成了 GraphQL Playground 调试工具。
启动一个 GraphQL 服务器只需要几行代码:
const { GraphQLServer } = require('graphql-yoga') const resolvers = { ... } const server = new GraphQLServer({ typeDefs, resolvers }) server.start(() => console.log('Server is running'))
其中,resolvers 是包含所有 Resolver 函数的对象,typeDefs 是包含 GraphQL Schema 定义的字符串。通过 GraphQLServer 构造函数和 start 方法,我们可以启动一个监听在本地某个端口的服务器,并使用 GraphQL Playground 来测试 API。
- 测试 API
使用 GraphQL Playground 工具,我们可以直观地测试 API 并查看响应结果。对于上述 Blog API,可以使用如下的查询语句:
// javascriptcn.com 代码示例 query { posts { id title content author { id name email } comments { id content author { id name } } } }
该查询会返回一个包含所有文章及其作者和评论的数据。我们也可以进行变更操作:
// javascriptcn.com 代码示例 mutation { createPost(title: "Hello world", content: "This is my first post", authorId: 123) { id title content author { name } } }
该变更操作将创建一篇新文章,并返回该文章的 ID、标题、内容和作者名。通过这些查询和变更操作,我们可以很方便地测试 API 的正确性并快速迭代和改进 API 的设计和实现。
总结
本文介绍了如何将一个已有的 REST API 转换为 GraphQL API,包括 API 设计、Schema 定义、Resolver 映射和服务器搭建等方面。通过将 REST API 转换为 GraphQL API,我们可以更好地利用 GraphQL 的灵活性和可扩展性,提高 API 的维护性和可用性,为前端开发带来更多的可能性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652fb56c7d4982a6eb0e4be5