GraphQL(四)- Query, Mutation, Subscription 在 ApolloGraph中的实现示例
本文讨论GraphQL中的Query,Mutation和Subscription,并给出ApolloGraph中的实现示例
Query和Mutation是GraphQL中的最基本操作,可以理解为:
query
=> GETmutation
=> POST, PUT, PATCH, DELETE
在GraphQL中两者被这样区分开,分离了读写操作,对于读写权限这块有个非常好的分隔。
在下面的示例中,我们定义了这样一个type:
type Employee {
name: String!
age: Int!
job: String!
hobbies: [String]
}
Query
我们通过下面的例子,查询内容:
后端示例:
const schema = gql`
type Employee {
name: String!
age: Int!
job: String!
hobbies: [String]
}
type Query {
employees: [Employee]
}
`
export const employeesDB = [
{
name: 'Rick',
age: 35,
job: 'Sale',
hobbies: ['Swimming', 'Reading']
},
{
name: 'Max',
age: 27,
job: 'Software engineer',
hobbies: ['Video games']
}
];
export const resolver = {
Query: {
employees: (parent: any, args: any, ctx: any, info: any) => {
return employeesDB;
},
}
};
const schema = makeExecutableSchema({
typeDefs: schema,
resolvers: resolver
});
const app = express();
const httpServer = createServer(app);
// Set up ApolloServer.
const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
ApolloServerPluginLandingPageLocalDefault({ embed: true }),
],
});
server.start().then(
() => {
server.applyMiddleware({ app });
const PORT = 4000;
// Now that our HTTP server is fully set up, we can listen to it.
httpServer.listen(PORT, () => {
console.log(`Server is now running on http://localhost:${PORT}${server.graphqlPath}`);
});
}
)
前端(Angular-Apollo):
graphql.module.ts
const PORT = 4000;
const uri = `http://localhost:${PORT}/graphql`;
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
return {
link: httpLink.create({uri}),
cache: new InMemoryCache(),
};
}
@NgModule({
exports: [ApolloModule],
providers: [
{
provide: APOLLO_OPTIONS,
useFactory: createApollo,
deps: [HttpLink],
},
],
})
export class GraphQLModule {}
Employee Component
const employeesQuery = gql`
query GetEmpoyeesAll {
employees {
name
age
job
hobbies
}
}
`;
@Component({
selector: 'app-employees-panel',
templateUrl: './employees-panel.component.html',
styleUrls: ['./employees-panel.component.scss'],
})
export class EmployeesPanelComponent implements OnInit {
employees: any[] = [];
loading = true;
error: any;
ngOnInit(): void {
this.apollo
.watchQuery({
query: employeesQuery,
})
.valueChanges.subscribe((result: any) => {
this.employees = result?.data?.employees;
this.loading = result.loading;
this.error = result.error;
});
}
}
Mutation
我们为上例添加一个方法,AddEmployee,定义对应类型和方法:
input AddEmployeeInput {
name: String!
age: Int!
job: String!
hobbies: [String]
}
type Mutation {
addEmployee(data: AddEmployeeInput):Employee
}
后端:
需要在上例的基础上,添加AddEmployee的resolver:
export const resolver = {
addEmployee: (parent: any, args: any, ctx: any, info: any) => {
const newEmployee = parent.data;
employeesDB.push(newEmployee);
return newEmployee;
}
};
前端:
在上例的基础上,前端增加一个添加按钮,绑定如下事件:
onCreateEmployee() {
const createEmployeeMutation = gql`
mutation {
addEmployee(employee: {
name: 'Lina',
age: 44,
job: 'manager',
hobbies: ['Reading', 'Dancing'],
}) {
name
}
}
`
this.apollo
.mutate({mutation: createBookMutation})
.subscribe((result: any) => {
this.apollo
.watchQuery({
query: createEmployeeMutation,
})
.valueChanges.subscribe((result: any) => {
this.employees = result?.data?.employees;
this.loading = result.loading;
this.error = result.error;
});
})
}
Subscription
Subscription 用于后端主动向前端发消息的情形,相较于Query和Mutation用得较少,通常用websocket添加Midware
在Apollo Graph中,需要引入第三方的library来实现,可以用graph-ws
,向前端添加一个计数器示例如下:
安装graph-ws
:
npm install graph-ws
gql中添加Subscription:
type Subscription {
count: Int
}
resolver:
export const resolver = {
Subscription: {
count: {
subscribe: () => {
let count = 0;
setInterval(() => {
count++
pubsub.publish('count', {
count
})
}, 1000)
return pubsub.asyncIterator('count');
}
}
}
}
后端引入Subscription,需要创建一个websocket实例作为Midware:
const schema = makeExecutableSchema({
typeDefs: schema,
resolvers: resolver
});
// Create an Express app and HTTP server; we will attach both the WebSocket
// server and the ApolloServer to this HTTP server.
const app = express();
const httpServer = createServer(app);
// Create our WebSocket server using the HTTP server we just set up.
const wsServer = new WebSocketServer({
server: httpServer,
path: '/graphql',
});
// Save the returned server's info so we can shutdown this server later
const serverCleanup = useServer({ schema }, wsServer);
// Set up ApolloServer.
const server = new ApolloServer({
schema,
csrfPrevention: true,
cache: 'bounded',
context: (req) => {
const request = req.req;
return {tags, tagGroups, users, request}
},
plugins: [
// Proper shutdown for the HTTP server.
ApolloServerPluginDrainHttpServer({ httpServer }),
// Proper shutdown for the WebSocket server.
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
ApolloServerPluginLandingPageLocalDefault({ embed: true }),
],
});
server.start().then(
() => {
server.applyMiddleware({ app });
const PORT = 4000;
// Now that our HTTP server is fully set up, we can listen to it.
httpServer.listen(PORT, () => {
console.log(`Server is now running on http://localhost:${PORT}${server.graphqlPath}`);
});
}
)
分类:
GraphQL
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具