GraphQL LogoGraphQL

对象类型

在很多情况下,你并不想从 API 返回一个数字或字符串。你想要返回一个具有自身复杂行为的对象。GraphQL 非常适合这种情况。

在 GraphQL 模式语言中,定义新对象类型的方式与我们在示例中定义 Query 类型的方式相同。每个对象都可以具有返回特定类型的字段和接受参数的方法。例如,在 传递参数 文档中,我们有一个方法来掷一些随机骰子

type Query {
rollDice(numDice: Int!, numSides: Int): [Int]
}

如果我们想随着时间的推移,基于随机骰子创建越来越多的方法,我们可以使用 RandomDie 对象类型来实现这一点。

type RandomDie {
roll(numRolls: Int!): [Int]
}
type Query {
getDie(numSides: Int): RandomDie
}

我们可以使用 ES6 类来代替 RandomDie 类型的根级解析器,其中解析器是实例方法。这段代码展示了如何实现上面的 RandomDie 模式

class RandomDie {
constructor(numSides) {
this.numSides = numSides
}
rollOnce() {
return 1 + Math.floor(Math.random() * this.numSides)
}
roll({ numRolls }) {
var output = []
for (var i = 0; i < numRolls; i++) {
output.push(this.rollOnce())
}
return output
}
}
var root = {
getDie: ({ numSides }) => {
return new RandomDie(numSides || 6)
},
}

对于不使用任何参数的字段,可以使用对象的属性或实例方法。因此,对于上面的示例代码,numSidesrollOnce 都可以用来实现 GraphQL 字段,因此该代码也实现了以下模式

type RandomDie {
numSides: Int!
rollOnce: Int!
roll(numRolls: Int!): [Int]
}
type Query {
getDie(numSides: Int): RandomDie
}

将所有这些放在一起,这里是一些运行带有此 GraphQL API 的服务器的示例代码

var express = require("express")
var { createHandler } = require("graphql-http/lib/use/express")
var { buildSchema } = require("graphql")
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type RandomDie {
numSides: Int!
rollOnce: Int!
roll(numRolls: Int!): [Int]
}
type Query {
getDie(numSides: Int): RandomDie
}
`)
// This class implements the RandomDie GraphQL type
class RandomDie {
constructor(numSides) {
this.numSides = numSides
}
rollOnce() {
return 1 + Math.floor(Math.random() * this.numSides)
}
roll({ numRolls }) {
var output = []
for (var i = 0; i < numRolls; i++) {
output.push(this.rollOnce())
}
return output
}
}
// The root provides the top-level API endpoints
var root = {
getDie: ({ numSides }) => {
return new RandomDie(numSides || 6)
},
}
var app = express()
app.all(
"/graphql",
createHandler({
schema: schema,
rootValue: root,
})
)
app.listen(4000)
console.log("Running a GraphQL API server at localhost:4000/graphql")

当你向返回对象类型的 API 发出 GraphQL 查询时,可以通过嵌套 GraphQL 字段名称来一次调用对象上的多个方法。例如,如果你想调用 rollOnce 来掷一次骰子,并调用 roll 来掷三次骰子,你可以使用以下查询来实现

{
getDie(numSides: 6) {
rollOnce
roll(numRolls: 3)
}
}

如果你使用 node server.js 运行这段代码,并浏览到 http://localhost:4000/graphql,你就可以使用 GraphiQL 来尝试这些 API。

这种定义对象类型的方式通常比传统的 REST API 更有优势。你不需要进行一次 API 请求来获取有关对象的简单信息,然后进行多次后续 API 请求来获取有关该对象的更多信息,你可以在一次 API 请求中获取所有这些信息。这可以节省带宽,使你的应用程序运行更快,并简化你的客户端逻辑。

到目前为止,我们所看到的每个 API 都是为返回数据而设计的。为了修改存储的数据或处理复杂的输入,学习关于 mutations 和 input types 会有所帮助。

继续阅读 →Mutations 和 Input Types