GraphQL学习与实践2(类型、传参与构造函数类型)

GraphQL学习与实践2(类型、传参与构造函数类型)

在上一节的已经成功搭建了一个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的面向对象的思想。
在这里插入图片描述在这里插入图片描述
两者区别在于:

区别buildSchemaGraphQLSchema
参数类型字符串对象
类名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)
GraphQL学习与实践4(模拟客户端请求)
GraphQL学习与实践5(连接数据库mongodb与mysql)

代码:
onsenOnly:https://github.com/onsenOnly/graphql-test

有缘请点颗星,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值