在本文中,我们将介绍如何在GraphQL中使用Mutation
和Subscription
类型来操作和监视数据的更改,而不仅仅是查询。请随时在官方文档.)中了解更多信息
为了简单起见,我们不会使用任何数据库或HTTPS请求,但知道如何使用模式和resolvers]设置基本的API是必要的。
安装
我们将使用graphql-yoga库来设置我们的服务器,并使用nodemon
让它自动重新加载。我们还需要一个像Prepros或[Babel)(https://babeljs.io/))这样的前处理器,这样我们才能使用JAVASCRIPT的最新功能。
1$ npm i graphql-yoga nodemon
样板设置
除了我们的服务器设置之外,我们只有一个空的‘USERS’数组和一个用于返回所有用户的简单模式和解析器。
1[label server.js]
2import { GraphQLServer } from 'graphql-yoga'
3
4const users = [];
5
6const typeDefs = `
7 type Query {
8 users: [User!]!
9 }
10
11 type User {
12 name: String!
13 age: Int!
14 }
15`;
16
17const resolvers = {
18 Query: {
19 user() {
20 return users;
21 }
22 }
23}
24
25const server = new GraphQLServer({ typeDefs, resolvers });
26
27server.start(() => console.log('server running'));
我们需要一个start
脚本,它将在我们的输出文件上运行nodemon:
1[label package.json]
2{
3 "name": "graphql-api",
4 "version": "1.0.0",
5 "description": "",
6 "main": "server.js",
7 "dependencies": {
8 "graphql-yoga": "^1.16.7"
9 },
10 "devDependencies": {
11 "nodemon": "^1.19.1"
12 },
13 "scripts": {
14 "start": "nodemon server-dist.js"
15 },
16 "author": "",
17 "license": "ISC"
18}
现在在终端中,您只需运行npm run start
即可。
在localhost:4000
处,我们应该启动[GraphQLname]并运行对Playground](https://github.com/prisma/graphql-playground){name}
的查询,返回我们的空数组。
创建突变
我们突变的语法与我们的查询的语法几乎相同。我们只需要声明我们想要什么选项,添加任何参数(如果有的话),并声明在完成时应该返回什么类型。
为了便于组织,通常不是内联添加所有的Out参数,而是将数据分解为其自己的特殊类型,称为)来命名输入,无论解析器以单词Input结尾,因此
addUser获得一个
AddUserInput`输入。
1[label server.js]
2const typeDefs = `
3 type Mutation {
4 addUser(data: AddUserInput): User!
5 }
6
7 input AddUserInput {
8 name: String!,
9 age: Int!
10 }
11`;
就像查询一样,我们可以访问args上的参数,并将新用户添加到数组中,然后返回它们。
1const resolvers = {
2 Query: {...},
3 Mutation: {
4 addUser(parent, args, ctx, info) {
5 const user = { ...args.data };
6
7 users.push(user);
8 return user;
9 }
10 }
11}
删除和更新突变
由于语法如此简单,因此几乎可以毫不费力地充实其他CRUD操作。
我们只需按名称搜索用户,就可以知道要删除或更新的项目。
1[label server.js]
2const typeDefs = `
3 type Mutation {
4 deleteUser(name: String!): User!
5 updateUser(name: String!, data: UpdateUserInput): User!
6 }
7
8 input UpdateUserInput {
9 name: String
10 age: Int
11 }
12`
13
14const resolvers = {
15 Query: { ... },
16 Mutation: {
17 deleteUser(parent, args, ctx, info) {
18 // We're just finding the index of the user with a matching name,
19 // checking if it exists, and removing that section of the array.
20 const userIndex = users.findIndex(user => user.name.toLowerCase() === args.name.toLowerCase());
21 if (userIndex === -1) throw new Error('User not found');
22
23 const user = users.splice(userIndex, 1);
24 return user[0];
25 },
26 updateUser(parent, args, ctx, info) {
27 const user = users.find(user => user.name.toLowerCase() === args.who.toLowerCase());
28 if (!user) throw new Error('User not found');
29
30 // This way, only the fields that are passed-in will be changed.
31 if (typeof args.data.name === "string") user.name = args.data.name;
32 if (typeof args.data.age !== "undefined") user.age = args.data.age;
33
34 return user;
35 }
36 }
37}
现在,在localhost:4000
处,您可以尝试此突变并再次查询我们的数组。
1mutation {
2 addUser(data: {
3 name: "Alli",
4 age: 48
5 }) {
6 name
7 age
8 }
9}
或在另一个选项卡中:
1mutation {
2 updateUser(name: "Alli", data: {
3 name: "Crusher",
4 age: 27
5 }) {
6 name
7 age
8 }
9}
♪订阅
我们可以使用特殊的Subscription
类型来监视数据的任何更改。语法非常类似于查询和突变,只需添加类型Subscription
,添加您想要它查看的内容,并返回您想要返回的内容。我们将返回一个定制类型,该类型将向我们发送回已更改的数据,并告诉我们它是创建、删除还是更新操作。
要使用订阅,我们需要使用GraphQL-YOGA中的PubSub
,并在进行其他操作之前对其进行初始化。在我们的订阅解析器中,我们将使用一个名为SUBSCRIBE‘的函数,该函数需要返回一个异步事件,我们将其命名为’user
。每当我们要将某些内容连接到此订阅时,我们都会使用此事件名称。
1[label server.js]
2import { GraphQLServer, PubSub } from 'graphql-yoga';
3
4const pubsub = new PubSub();
5
6const typeDefs = `
7type Subscription {
8 user: UserSubscription!
9}
10
11type UserSubscription {
12 mutation: String!
13 data: User!
14}
15`
16
17const resolvers = {
18 Query: { ... },
19 Mutation: { ... },
20 Subscription: {
21 user: {
22 subscribe() {
23 return pubsub.asyncIterator('user');
24 }
25 }
26}
27}
我们的订阅本身是设置的,并且在生成的GraphQL文档中可用,但它不知道何时启动或返回什么。回到我们的变化中,我们将添加pubsub.Publish
来链接到我们的user
事件,并将我们的数据传回。
1const resolvers = {
2 Query: { ... },
3 Mutation: {
4 addUser(parent, args, ctx, info) {
5 const user = { ...args.data };
6
7 users.push(user);
8
9 // We'll just link it to our user event,
10 // and return what type of mutation this is and our new user.
11 pubsub.publish("user", {
12 user: {
13 mutation: "Added",
14 data: user
15 }
16 });
17
18 return user;
19 },
20 deleteUser(parent, args, ctx, info) {
21 const userIndex = users.findIndex(
22 user => user.name.toLowerCase() === args.who.toLowerCase()
23 );
24 if (userIndex === -1) throw new Error("User not found");
25
26 const user = users.splice(userIndex, 1);
27
28 pubsub.publish("user", {
29 user: {
30 mutation: "Deleted",
31 data: user[0]
32 }
33 });
34
35 return user[0];
36 },
37 updateUser(parent, args, ctx, info) {
38 const user = users.find(
39 user => user.name.toLowerCase() === args.who.toLowerCase()
40 );
41 if (!user) throw new Error("User not found");
42
43 if (typeof args.data.name === "string") user.name = args.data.name;
44 if (typeof args.data.age !== "undefined") user.age = args.data.age;
45
46 pubsub.publish("user", {
47 user: {
48 mutation: "Updated",
49 data: user
50 }
51 });
52
53 return user;
54 }
55 },
56 Subscription: { ... }
57};
在本地主机:4000
上,我们可以打开一个新选项卡并运行以下订阅。你应该看到一个‘监听...’。用一个小小的旋转轮发送信息。在另一个选项卡中,我们现在可以运行我们过去的任何其他突变,我们的订阅将自动返回完成了什么和更改了什么。
1subscription {
2 user {
3 mutation
4 data {
5 name
6 age
7 }
8 }
9}
总结
我希望这对理解如何设置带有突变和订阅的GraphQL API有帮助。如果在设置时有任何问题,您可以随时查看This repo.