graphQL入门基础(一)

1. 什么是GraphQL?

A query language for your API

官网给他的定义是一门API的查询语言。他会给你API中的数据一份完整的描述,这样客户端就可以根据这份描述来确定他具体需要什么。下面总结一下他的特点:

  1. 根据需要查询数据。客户端可以发送一个GraphQL到服务端API,只获取客户端想要的数据。查询总是会返回预测的结果,说白了就是你想要什么就会拿到什么(前提是API有想要的数据)。
  2. 在一份请求中获取多种数据。GraphQL不只是会访问某一种资源,还可以访问数据之间的引用,即使这些数据后端需要从多个URL加载,这个速度也是非常快的。
  3. 使用类型系统描述什么是可以获取的。GraphQL API根据类型和字段进行组织。使用类型来确保客户端只会获取肯能的内容,并且会提供很明确的错误反馈。避免了服务端手动对请求数据进行解析。
  4. 强大的开发工具。这个也是我非常喜欢的一点,可以很直观的知道可以从服务端获取哪些数据,数据结构是怎样的,并且还会有每个字段的描述,简直比开发文档还要方便。

既然他是一个这么好的东西,现在都有谁在用呢,靠谱么?

由于它是由Facebook提出的,所以从2012年开始Facebook的移动应用就已经开始使用GrqphQL了。而且现在Github的API v4也已经使用了GraphQL。目前该项已经技术比较成熟,可以在项目中进行使用了。

2. 项目搭建

本项目的目的是搭建一个由GraphQL建立的服务端,并且提供查询工具。

2.1 技术选择

主要的就下面几个

Koa GraphQL TypeScript GraphiQL

还有几个工具库

graphql-relay koa-graphiql koa-graphql superagent

2.2 搭建

服务端基础搭建就不做介绍了,就是使用koa + TypeScript搭建了一个简单的服务器。
由于GeaphQL是基于类型和字段的,那么先对数据进行类型定义吧。

先简单的来一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
user.ts
const GQUser = new GraphQLObjectType({
name: 'GQUser',
fields: {
name: {
type: GraphQLString,
resolve(user) {
return user.name;
},
},
age: {
type: GraphQLInt,
resolve() {
return 22
}
}
}
});

在这里name就是定义的类型名字,fields就是他所具备的字段,当然每个字段也有自己的类型,resolve函数反回的是这个字段最终的值。它的参数来自使用它的类型的resolve返回,具体下面介绍。

类型定义完成后就可以使用这个类型了,
首先定义查询入口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
schema.ts
class User {
public name: string;
public age: number;
constructor() {
this.name = 'lxc';
this.age = 22;
}
}
const Query = new GraphQLObjectType({
name: 'Query',
fields: () => ({
user: {
type: GQUser,
description: '用户',
resolve: async () => {
return new User();
}
}
})
});
export default new GraphQLSchema({
query: Query,
});

发现这里也有一个类型:query,这是每个GraphQL都会有的一个类型,他和其他类型没有什么区别,唯一特殊的是它是程序查询的入口。
我在这里给query类型添加了一个叫user的字段,它的类型是我们上面定义的GQUser,同时他的resolve函数返回了一个User对象,那么这个返回的对象就会传给GQUser的的resolve函数。

下面就是建立GraphQL服务了,由于使用了koa-graphql ,这个过程非常简单

1
2
3
4
5
6
const graphqlHTTP = require('koa-graphql');
router.all('/graphql', graphqlHTTP({
schema,
graphiql: true,
}));

这样就搭建了一个GraphQL的服务,同时为了方便用户查询数据结构和描述,这里使用了GraphiQL开发工具。

2.3 查询

查询数据

1
2
3
4
5
query{
user {
name
}
}

获得结果是

1
2
3
4
5
6
7
{
"data": {
"user": {
"name": "lxc",
}
}
}

这里就会发现,我在这里只希望拿到user的name属性,服务端返回的也是只有name属性,并没有多返回什么东西。我想要拿什么就可以在查询语句中改什么,并不需要对服务端的代码进行任何的改动,无形中降低了很多开发量,减少了很多沟通,提高了开发的速度和效率。