1. 什么是graphql
GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。直译过来就是图查询语言,所以当他在处理图状数据的时候,会有很大的优势。
2. graphql的优势
Ask for what you need 要什么点什么,参数不多不少刚刚好
只需一次请求,获取多个资源
API演进过程,平滑无痕
3.举个🌰
比如我们现在后端定义了一个用户user模块,以及一个针对user模块的查询Query,代码大概如下:
type user {
telephone: String
QQ: String
id: ID!
name: String!
age: Float
hobby: [String]
}
type Query {
userQuery(id: String!): user!
}
这里可以看出graphql中实体的参数都是有类型、以及是否可为空的校验。
然后Query和Mutation是graphql里面定义的操作关键字,用来表示查询请求以及更新请求,在单个请求的情况下,两者只有语义上的区别,但是在多个资源同时在一次请求中发起时,多个query会并行执行,而Mutation则会根据顺序依次执行。
接下来我们再从前端发起一个请求,查询某个用户的信息,请求的参数形式大概如下
query userQuery($id: String!) {
user(id: $id) {
name
age
telephone
}
}
这是一个针对用户user实体的请求,并且告诉接口,我只要知道name、age、telephone这三个信息,那么这次的请求成功后,接口就只会返回这三个参数,不多也不少。
{
data: {
user: {
name: "张三",
age: 18,
telephone: "13012345678"
}
}
}
接下来如果,我们的接口要进行演进,需要新增的宠物信息的数据,宠物信息与用户相关联,但是单独存放在另一个数据表中。那么只需要将schema声明改成这样:
type user {
telephone: String
QQ: String
id: ID!
name: String!
age: Float
hobby: [String]
pet: [pet]
}
type pet {
name
temper
species
age
weight
}
type Query {
userQuery(id: String!): user!
}
只需要新增一个宠物的实体定义,并且把它放在user实体的下面相关联。前端同时把需要查询的宠物信息参数,也加到请求中来,就可以请求得到宠物信息相关字段了。
query userQuery($id: String!) {
user(id: $id) {
name
age
telephone
pet {
name
species
}
}
}
接口的升级过程也是非常的平滑,并且多个资源的查询在一次请求中就已经完成了。同时之前只查询用户信息的情况也能继续兼容,只需要在前端发起请求时去掉pet相关请求参数即可。
上面pet和user是有关联关系的,如果有另一个与user无关联的实体,也是可以合并到一次请求中查询得到资源的:
query userQuery($id: String!) {
user(id: $id) {
name
age
telephone
pet {
name
species
}
}
activity {
id
name
createdTime
}
}
可以看到虽然graphql查询的数据是图状结构的,但是处理起来最后返回给前端的其实是树状结构的数据,每个查询(query)或修改(mutation)返回的结构始终有一个根节点,而且能看出节点之间由上而下的父子关系。
vs restful API
restful API中使用GET、PUT、POST等http方法来约定对资源的操作动作,graphql使用自己Query、Mutation来定义操作,使用post方法发起http请求,将查询参数语句放在body之中。
restful API可使用http状态码来表示接口的异常错误,而graphql返回的http状态码始终是200,只有将错误信息错误码再次封装放在返回体中。
restful API可以使用swagger等工具来展示接口文档,graphql中数据结构schema即是接口文档。
graphql不能使用http缓存,因为graphql的请求通常是http post方法。所以在graphql中要使用缓存,只有在客户端集成,不过一般的graphql客户端包(比如Apollo)都已集成了缓存功能。