GraphQL 简介及其优势
\n\nGraphQL 是一种 API 查询语言和运行时环境,由 Facebook 开发。与 REST 不同,在 REST 中您会获得固定的数据结构,而 GraphQL 允许客户端仅请求其所需的数据。这使得 API 更加灵活和高效。
\n\n在本逐步教程中,我们将使用 Node.js 创建一个完整的基于 JavaScript 的 GraphQL API。您将学习如何配置服务器、定义模式、处理查询和变更。文章结束时,您将拥有一个可运行的 API,随时可集成到任何项目中。
\n\n1. 项目设置与依赖安装
\n\n首先,创建一个新的 Node.js 项目并安装必要的包。我们将使用 apollo-server——一个用于创建 GraphQL 服务器的流行库。
步骤 1:初始化项目
\nmkdir graphql-tutorial\ncd graphql-tutorial\nnpm init -y\n\n步骤 2:安装 Apollo Server 和 GraphQL
\nnpm install apollo-server graphql\n\n安装完成后,创建主文件 index.js,我们的服务器将位于其中。
2. 创建基础 GraphQL 服务器
\n\n现在,编写一个最小的服务器,用于接收请求并返回响应。为此,我们需要定义模式(schema)和解析器(resolvers)。
\n\n步骤 1:定义数据类型
\n创建一个简单的 Book 类型,包含 id、title 和 author 字段。
const { ApolloServer, gql } = require('apollo-server');\n\n// GraphQL 模式\nconst typeDefs = gql`\n type Book {\n id: ID!\n title: String!\n author: String!\n }\n\n type Query {\n books: [Book]\n book(id: ID!): Book\n }\n`;\n\n// 示例数据(实际项目中为数据库)\nconst books = [\n { id: '1', title: '战争与和平', author: '列夫·托尔斯泰' },\n { id: '2', title: '罪与罚', author: '费奥多尔·陀思妥耶夫斯基' },\n { id: '3', title: '大师与玛格丽特', author: '米哈伊尔·布尔加科夫' }\n];\n\n// 解析器——返回数据的函数\nconst resolvers = {\n Query: {\n books: () => books,\n book: (parent, args) => books.find(book => book.id === args.id)\n }\n};\n\n// 创建服务器\nconst server = new ApolloServer({ typeDefs, resolvers });\n\n// 启动服务器\nserver.listen().then(({ url }) => {\n console.log(`🚀 服务器已就绪,地址:${url}`);\n});\n\n步骤 2:启动与测试
\n执行命令 node index.js,然后在浏览器中打开 http://localhost:4000。您将看到 GraphQL Playground——一个用于测试查询的工具。
尝试执行一个简单查询:
\n{\n books {\n title\n author\n }\n}\n\n响应应包含指定字段的书籍列表。
\n\n3. 添加变更与扩展模式
\n\n现在,添加通过变更修改数据的功能。这将允许创建、更新和删除记录。
\n\n步骤 1:在模式中定义变更
\nconst typeDefs = gql`\n type Book {\n id: ID!\n title: String!\n author: String!\n }\n\n input BookInput {\n title: String!\n author: String!\n }\n\n type Query {\n books: [Book]\n book(id: ID!): Book\n }\n\n type Mutation {\n addBook(input: BookInput!): Book\n deleteBook(id: ID!): Book\n }\n`;\n\n步骤 2:实现变更的解析器
\nconst resolvers = {\n Query: {\n books: () => books,\n book: (parent, args) => books.find(book => book.id === args.id)\n },\n Mutation: {\n addBook: (parent, args) => {\n const newBook = {\n id: String(books.length + 1),\n title: args.input.title,\n author: args.input.author\n };\n books.push(newBook);\n return newBook;\n },\n deleteBook: (parent, args) => {\n const index = books.findIndex(book => book.id