一个GraphQL查询在被验证后,GraphQL服务器会将之执行。
- 一个例子
type Query {
human(id: ID!): Human
}
type Human {
name: String
appearsIn: [Episode]
starships: [Starship]
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
type Starship {
name: String
}
{
human(id: 1002) {
name
appearsIn
starships {
name
}
}
}
{
"data": {
"human": {
"name": "Han Solo",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"starships": [
{
"name": "Millenium Falcon"
},
{
"name": "Imperial shuttle"
}
]
}
}
}
- GraphQL工作原理:GraphQL查询中的每个字段视为返回子类型的父类型函数或方法,每个类型的每个字段都有一个resolver函数支持,该函数由GraphQL服务器开发人员提供,当一个字段被执行时,相应的resolver被调用产生下一个值。如果字段产生标量值,则执行完成,如果产生对象,则该查询将继续执行该对象对应的解析器,知道返回标量值。
根字段 & 解析器
GraphQL服务端应用顶层,必有一个类型代表所有进入GraphQL API可能的入口,成为
Root
/Query
类型上述例子中查询了
human
字段,接收一个参数id,服务端的解析器可能实现如下
Query: {
human(obj, args, context) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
}
- 解析器函数接收3个参数:
- obj上一级对象,如果字段输入根节点查询,通常不会被使用
- args可以提供在GraphQL查询中传入的参数
- context被提供给所有解析器,并且持有重要的上下文信息,比如当前登入的用户、数据库访问对象
异步解析器
human(obj, args, context) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
- context提供了数据库访问对象,调用数据库访问方法,返回一个Promise,在回调中,实例化一个新的Human对象
- 在执行期间,如果异步操作没有完成,则GraphQL会一直等待下去,所以需要关注异步处理的优化
不重要的解析器
对于产生的Human,GraphQL会继续递归执行下去
Human: {
name(obj, args, context) {
return obj.name
}
}
- name字段,返回上层回调产生的new Human对象上的name属性