在上一节的已经成功搭建了一个hello world的基础上,这里来说一下GraphQL类型相关及其一些实践操作、搭建一个schema等。
Type System
几乎任何一门语言,都是具有类型的。GraphQL常用的类型有:
- 标量类型
- 列表和非空
- 枚举类型
- 对象类型
- 接口
- 联合类型
- 输入类型
...
标量类型
GraphQL 自带一组默认标量类型:
- Int:有符号 32 位整数。
- Float:有符号双精度浮点值。
- String:UTF‐8 的字符序列。
- Boolean:true或false。
- ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;
列表和非空
默认情况下,每种类型都会返回null作为任何标量。与此相对的可以使用感叹号(!)表示非空类型。例如:String!表示非空字符串。
和大多数语言类似的,使用中括号来代表列表,例如:[Int]表示一个整型的列表。
枚举类型
枚举类型是一种特殊的标量,它限制在一个特殊的可选值集合内。例如:
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
这表示了无论在schema中哪里使用了Episode ,其返回值肯定是NEWHOPE、EMPIRE、JEDI三个值其中一个。(注意,各种语言实现的 GraphQL 服务会有其独特的枚举处理方式。但对于JavaScript 在ES5中没有支持,些枚举值可能就被内部映射成整数值。但这都是内部的细节,并不会影响使用。)
对象类型
GraphQL schema 中的最基本的组件是对象类型。它就表示你可以从服务上获取到什么类型的对象,以及这个对象有什么字段。例如:
type Character {
name: String!
appearsIn: [Episode!]!
}
Character 是一个 GraphQL 对象类型,表示其是一个拥有一些字段的类型。
实例:修改test2-express.js中的hello world的demo为如下:
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type objName {
name:String
}
type Query {
hello:objName
}
`);
// The root provides the top-level API endpoints
var root = {
hello: () => { return { name: 'hello world' } },
}
var app = express();
app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, }));
app.listen(4000); console.log('Running a GraphQL API server at localhost:4000/graphql');
执行node test2-express.js。打开浏览器的调试工具,输入:
{
hello {
name
}
}
如图:
上面把hello中的String类型改为了对象类型的objName,objName中带有String类型的name属性。
传参
这里以官网的例子为例:
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type Query {
rollDice(numDice: Int!, numSides: Int): [Int] }
`
);
// The root provides a resolver function for each API endpoint
var root = {
rollDice: function ({ numDice, numSides }) {
var output = [];
for (var i = 0; i < numDice; i++) {
output.push(1 + Math.floor(Math.random() * (numSides || 6)));
}
return output;
}
};
var app = express();
app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, }));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');
执行node test5-args.js。打开浏览器的调试工具,输入:
{
rollDice(numDice:3,numSides:6)
}
如图:
模拟客户端发送请求?
这里以RESTClient为工具进行模拟客户端发送请求,如图:
body:{"query":"{rollDice(numDice:3,numSides:6)}"}
来自官网对于对象类型的例子,新建一个test6-object.js文件:
var express = require('express');
var graphqlHTTP = require('express-graphql');
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: function ({ numSides }) {
return new RandomDie(numSides || 6);
}
}
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');
执行node test6-object.js。打开浏览器的调试工具,输入:
{
getDie(numSides:3){
roll(numRolls:2)
rollOnce
}
}
如图:
在上面的例子中,看到了是自定义了一个类型RandomDie,在类中定义有三个属性,分别为:numSides 、rollOnce、roll。在上例中就显示了两个方法的调用。如果此时需要显示numSides属性的话,只需要加上numSides的属性就可以获取到对应的返回,如图:
构造类型
对于许多应用程序,您可以在应用程序启动时定义固定模式,并使用GraphQL模式语言对其进行定义。在某些情况下,以构造类型是很有用的。
而且,使用GraphQLSchema构造类型来构建架构,可以把对应的schema作为单独的对象创建,这样就方便我们的项目目录管理了。
直接上官网的例子来对比说明,
过往的方式:
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
var schema = buildSchema(`
type User {
id: String
name: String
}
type Query {
user(id: String): User
} `
);
// Maps id to User object
var fakeDatabase = {
'a': {
id: 'a',
name: 'alice',
},
'b': {
id: 'b',
name: 'bob',
},
};
var root = {
user: function ({ id }) {
return fakeDatabase[id];
}
};
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');
执行node test6-object.js。打开浏览器的调试工具,输入:
{
user(id:"a"){
name,
id
}
}
如图:
使用GraphQL Schema来使用相同的API,见下:
var express = require('express');
var graphqlHTTP = require('express-graphql');
var graphql = require('graphql');
// Maps id to User object
var fakeDatabase = {
'a': {
id: 'a',
name: 'alice',
},
'b': {
id: 'b',
name: 'bob',
},
};
// Define the User type
var userType = new graphql.GraphQLObjectType({
name: 'User',
fields: {
id: {
type: graphql.GraphQLString
},
name: {
type: graphql.GraphQLString
},
}
});
// Define the Query type
var queryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: {
user: {
type: userType,
// `args` describes the arguments that the `user` query accepts
args: {
id: {
type: graphql.GraphQLString
}
},
resolve: function (_, { id }) {
return fakeDatabase[id];
}
}
}
});
var schema = new graphql.GraphQLSchema({ query: queryType });
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');
对比一下buildSchema和GraphQLSchema的创建方式,可以明显的发现使用GraphQLSchema的方式其定义的类型和原来的buildSchema方式的类型不一样了,并且GraphQLSchema更接近OOP的面向对象的思想。

两者区别在于:
区别 | buildSchema | GraphQLSchema |
---|---|---|
参数类型 | 字符串 | 对象 |
类名 | type 字符后面 | 参数对象的 name 属性 |
属性定义 | 定义在类型后,键值对形式 | 定义在参数对象 fields 属性中,值为对象,每个属性名为键名,值也是对象 |
同样GraphQLSchema 也有其对应的类型,例如:
GraphQLEnumType、GraphQLFloat、GraphQLID。GraphQLInputObjectType。GraphQLInt、GraphQLInterfaceType、GraphQLList、GraphQLNonNull等等。
具体可以参考:https://graphql.org.cn/graphql-js/type.html
更多:
GraphQL学习与实践1(入门介绍)
GraphQL学习与实践2(类型、传参与构造函数类型)
GraphQL学习与实践3(Mutations And Input Types)
网友评论