GraphQL学习——执行

一个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属性

推荐阅读更多精彩内容