2、GraphQL核心概念:Schema、Query、Mutation、Subscription的定义与作用

好,咱们直接进入正题。

GraphQL 的核心,说白了就四个东西:SchemaQueryMutationSubscription。你把这四个搞明白了,GraphQL 就算入门了。我当年刚接触时,也觉得概念多,但用起来其实就那几招。

2.1 Schema:你的数据契约

Schema 是什么?我习惯把它理解成前后端之间的合同。你前端能查什么数据,后端能返回什么数据,全写在这份合同里。

举个例子,你在写一个用户列表功能。后端说:“我给你 id、name、email 这三个字段。” 那前端就只能拿这三个。多一个没有,少一个不行。这就是 Schema 的约束力。

核心要点:Schema 定义了数据的形状和类型。它是强类型的,每个字段都得有明确的类型。

来看一段典型的 Schema 定义:

type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}

注意那个感叹号 !,它表示这个字段不能为空。我在项目中遇到过好几次,前端没处理空值,结果页面直接崩了。嗯,从那以后我特别留意这个感叹号。

2.2 Query:查数据,就这么简单

Query 就是查数据用的。你想想看,REST API 里你要查用户,得调 /api/users,查文章得调 /api/posts。但在 GraphQL 里,你只需要一个 Query 入口。

Query 的定义长这样:

type Query {
  users: [User!]!
  user(id: ID!): User
  posts: [Post!]!
}

前端发起查询时,可以这样写:

query GetUsers {
  users {
    id
    name
    email
  }
}

你发现没?前端想要什么字段就写什么字段。不会多返回一个你不需要的字段。我记得有一次做移动端优化,接口返回的数据量太大,用 GraphQL 后,流量直接降了 40%。这就是按需查询的魅力。

小技巧:我建议每个 Query 都起个名字,比如 GetUsersGetPostById。这样调试时一眼就能看出是哪个查询出了问题。

2.3 Mutation:改数据,有规矩

Mutation 是用来增删改数据的。为什么叫 Mutation 不叫 Update?因为 GraphQL 的设计哲学是:任何修改数据的操作,都应该显式地声明为 Mutation。

定义 Mutation 的语法和 Query 很像:

type Mutation {
  createUser(name: String!, email: String!): User!
  deleteUser(id: ID!): Boolean!
}

前端调用时:

mutation CreateUser($name: String!, $email: String!) {
  createUser(name: $name, email: $email) {
    id
    name
    email
  }
}

这里有个坑,我曾经踩过:Mutation 执行完后,一定要返回修改后的数据。比如创建用户后,返回新用户的 id。这样前端才能更新本地状态,不用再发一次 Query。

注意:Mutation 是串行执行的。你连续发两个 Mutation,第二个会等第一个执行完。但 Query 是并行的,别搞混了。

2.4 Subscription:实时数据,像听广播

Subscription 是 GraphQL 里最酷的功能之一。它让前端可以订阅某个事件,后端有数据更新时,主动推给前端。

你想想看,聊天应用、实时通知、股票行情……这些场景用 Subscription 再合适不过了。

定义 Subscription:

type Subscription {
  newPost: Post!
  userUpdated(id: ID!): User!
}

前端订阅:

subscription OnNewPost {
  newPost {
    id
    title
    content
    author {
      name
    }
  }
}

一旦有人创建了新文章,后端就会把数据推过来。前端不用轮询,不用手动刷新。我个人觉得,这是 GraphQL 比 REST 强很多的地方。

实战建议:Subscription 底层通常用 WebSocket 实现。如果你项目里用 Apollo Client,它已经帮你封装好了。但要注意,Subscription 的连接数不能太多,否则服务器压力会很大。

2.5 四者关系速览

概念 作用 类比 REST 执行方式
Schema 定义数据结构和类型 API 文档 + 类型定义 静态定义
Query 查询数据(读) GET 请求 并行执行
Mutation 修改数据(写) POST/PUT/DELETE 串行执行
Subscription 实时数据推送 WebSocket 长连接

2.6 避坑指南

最后,分享几个我实际项目中遇到的坑:

  • Schema 别写太大。我见过一个项目,一个 Schema 文件 3000 行。后来拆成多个模块,用 extend type 合并,清爽多了。
  • Mutation 记得返回数据。不返回的话,前端还得再查一次,多一次网络开销。
  • Subscription 别滥用。不是所有实时场景都需要 Subscription。比如用户列表,每 30 秒轮询一次就够了,没必要开长连接。
  • 命名规范要统一。我习惯 Query 用 getXxx,Mutation 用 createXxxupdateXxxdeleteXxx。团队里统一了,代码可读性会好很多。

嗯,这四个概念讲完了。说白了,Schema 是蓝图,Query 是查,Mutation 是改,Subscription 是实时监听。你把这四个搞明白,GraphQL 的基本功就算扎实了。

下一章,咱们会动手写一个完整的 Schema,到时候你就知道这些概念怎么落地了。