前言
RESTful API 是目前开发 Web 应用程序时最常用的 API 架构。虽然它非常流行,但它的缺点也很明显,其中最大的问题就是当需要多次请求才能从服务器获取所需的信息时,会造成网络延迟和性能问题。
GraphQL 是一种新型的 API 架构,它提供了比 RESTful API 更为高效的方式来获取所需的信息。GraphQL 具有很多优点,最大的优势是能够减少网络请求次数,从而提高性能和减少延迟。
本文将介绍如何使用 GraphQL 实现 RESTful API 的 CRUD 操作,包含详细的内容和示例代码。希望能够帮助读者了解 GraphQL,并且在日常工作中使用 GraphQL 来解决问题。
什么是 GraphQL
GraphQL 是由 Facebook 开发的一种 API 架构,它允许客户端指定需要获取的数据,并且能够将多个请求合并成一个请求。GraphQL 与 RESTful API 相比,最大的不同点在于客户端指定所需的数据,而不是从服务器获取所有数据。
GraphQL 的数据模型是一张图,所有的数据都是基于这张图构建的。每个节点都对应一个类型,每个类型都有一组字段,这些字段可以是标量类型(如字符串、数字等),也可以是另一个类型。客户端可以通过 GraphQL 查询指定需要的字段,而不必获取整张图所包含的所有字段。
GraphQL 还支持以便捷的方式进行数据添加、修改和删除。因此,它被广泛地应用于开发 Web 应用程序和移动应用程序。
GraphQL 的优点
GraphQL 相比于 RESTful API 具有很多优点,主要有以下几点:
1. 查询灵活
GraphQL 允许客户端指定需要获取的数据,而不是从服务器获取所有数据。客户端可以自由组合所需要的字段,从而充分利用网络带宽。这相比于 RESTful API 需要多次请求获取所需数据,显得更加高效和灵活。
2. 强类型
GraphQL 是一种强类型语言,它的类型系统非常严格。通过 GraphQL 查询时,客户端必须指定要获取的字段以及字段所对应的类型。这个过程是通过定义 GraphQL Schema 来完成的,这样可以在编译时发现类型问题,显得更加安全。
3. 多端交互
GraphQL 适用于多种客户端,包括 Web 应用程序、移动应用程序和 IoT 设备。客户端可以使用任何语言或框架来与 GraphQL 服务器进行交互。
4. 容易扩展
GraphQL 具有非常灵活的数据结构,使得它容易扩展。如果需要添加新的字段或类型,则只需要更改 GraphQL Schema,而无需对现有程序进行修改。这也为代码的维护和升级提供了极大的便利。
GraphQL 的缺点
GraphQL 虽然具有很多优点,但也有一些缺点。
1. 学习曲线陡峭
GraphQL 的学习曲线相对于传统的 RESTful API 较陡峭。需要学习 GraphQL Schema、类型系统、查询语言等多个概念,并且服务器端和客户端都需要使用 GraphQL。
2. 多余的数据传输
GraphQL 可以避免多次请求所需数据的问题,但同时也会传输一些不必要的数据。因为客户端只能查询其需要的字段,所以可能会查询到其不需要的字段,导致网络传输的多余数据量增加。
3. 难以缓存
由于客户端请求的字段可能是任意组合,GraphQL API 非常难以缓存。网络请求可能会因为缓存操作失败而变得显得更慢。
GraphQL 实现 CRUD 操作
下面将介绍如何使用 GraphQL 实现 RESTful API 的 CRUD 操作。
安装相关依赖
在开始实现之前,需要先安装一些必要的依赖。这里使用 Node.js 和 Express 框架,在项目根目录下执行以下命令安装需要的依赖。
npm install express express-graphql graphql
定义 GraphQL Schema
在开始实现之前,需要先定义 GraphQL Schema。GraphQL Schema 是一个由类型和字段组成的结构,它定义了所有可查询和可修改的数据。
在本示例中,我们定义一个 Todo 类型,以及它所具有的字段,包括 id、text 和 completed。同时,我们也定义了 Query 和 Mutation 类型,并且编写了查询和修改逻辑。
// javascriptcn.com 代码示例 const { buildSchema } = require("graphql"); const schema = buildSchema(` type Todo { id: ID! text: String! completed: Boolean! } type Query { getTodos: [Todo] getTodoById(id: ID!): Todo } type Mutation { addTodo(text: String!): Todo updateTodoCompleted(id: ID!, completed: Boolean!): Todo } `); module.exports = schema;
编写 Resolvers
在定义了 GraphQL Schema 之后,需要实现 Resolvers,这里的 Resolvers 是指处理 GraphQL 查询和修改逻辑的代码。查询逻辑和修改逻辑都是通过 Resolvers 实现的。
在本示例中,我们编写了查询逻辑和修改逻辑的 Resolvers。其中查询逻辑是通过查询 MongoDB 数据库实现的,修改逻辑是通过更新 MongoDB 数据库实现的。
// javascriptcn.com 代码示例 const Todo = require("./models/todo"); const resolvers = { getTodos: async function () { try { const todos = await Todo.find(); return todos; } catch (error) { console.log(error); } }, getTodoById: async function ({ id }) { try { const todo = await Todo.findById(id); return todo; } catch (error) { console.log(error); } }, addTodo: async function ({ text }) { try { const todo = new Todo({ text, completed: false, }); await todo.save(); return todo; } catch (error) { console.log(error); } }, updateTodoCompleted: async function ({ id, completed }) { try { const todo = await Todo.findByIdAndUpdate( id, { completed }, { new: true } ); return todo; } catch (error) { console.log(error); } }, }; module.exports = resolvers;
初始化服务器
在完成了 GraphQL Schema 和 Resolvers 的定义之后,需要初始化服务器。这里使用 Express 框架和 express-graphql 中间件来实现这个过程。
// javascriptcn.com 代码示例 const express = require("express"); const graphqlHTTP = require("express-graphql"); const mongoose = require("mongoose"); const schema = require("./schema"); const resolvers = require("./resolvers"); mongoose.connect("mongodb://localhost:27017/graphql_crud", { useNewUrlParser: true, }); const app = express(); app.use( "/graphql", graphqlHTTP({ schema, rootValue: resolvers, graphiql: true, }) ); app.listen(3000, () => console.log("Server started on port 3000."));
测试 GraphQL API
在完成了服务器的初始化之后,可以通过访问 http://localhost:3000/graphql 来测试 GraphQL API。这里使用 GraphiQL 工具来测试 API。
查询所有 Todos
query { getTodos { id text completed } }
根据 ID 查询 Todo
query { getTodoById(id: "611b50fb9f2f390ff8d6fea1") { id text completed } }
添加 Todo
// javascriptcn.com 代码示例 mutation { addTodo( text: "Learn GraphQL" ) { id text completed } }
修改 Todo 状态
// javascriptcn.com 代码示例 mutation { updateTodoCompleted( id: "611b50fb9f2f390ff8d6fea1", completed: true ) { id text completed } }
总结
本文介绍了如何使用 GraphQL 实现 RESTful API 的 CRUD 操作。GraphQL 具有很多优点,最大的优势是能够减少网络请求次数,从而提高性能和减少延迟。了解了 GraphQL 的概念和定义之后,可以开始实现 GraphQL CRUD API,这里通过一个示例来演示了如何定义 GraphQL Schema、编写 Resolvers 和初始化 Express 服务器。
虽然 GraphQL 具有很多优点,但也存在不足之处,如高学习曲线、难以缓存等。开发者需要根据实际情况考虑是否使用 GraphQL,毕竟在某些场景下,传统的 RESTful API 仍然是更好的选择。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653a05a27d4982a6eb3be99b