GraphQL教程

时间:2023-02-10 11:14:11

前几年出现了一个叫GraphQL的新东西,听说现在不少公司都要会,但这东西由于理念比较新,理解起来有点难,这里为了降低大家的学习门槛,就用尽量通俗易懂的语言来说说什么是GraphQL和GraphQL怎么用,帮助大家快速理解。

首先来谈谈我个人理解的GraphQL的作用。现在it开发的流程基本上都是后端造api,前端调后端的api。一个项目接口往往有几百上千个,如果后端没有编写文档,前端一要用接口就得找后端问接口名、接口参数、返回值等等,时间一久后端同学就烦了,心想,要是有一种东西能给我自动生成接口的使用方法就好了,于是就捣鼓出了这个GraphQL,这个东西是这样:程序自动生成一份接口使用说明,后端给前端一个地址,这个地址给前端提供所有可用接口的信息,用一些工具打开这个地址,前端只要输入接口名称就能自动获得接口参数和返回值。

还有一点,有些后端同学比较偷懒,比如前台明明只要一个文章详情,结果后端同学没有过滤,直接把数据库里查出来的整个文章对象返回给了前端,包括了很多用不到的属性,这就浪费了流量和性能,GraphQL由于要求前端指定需要获取的字段,也可以预防这类问题

当然这只是通俗说法,背后还有很多业务上的考虑,其他人说得比我好,想深入了解的可以参考其他文章。

GraphQL对原有项目的影响是比较小的,虽然是数据查询语言,GraphQL不改变原有的数据存储方式,原先是存在mysql还是mongodb我都不管,GraphQL只改变前端获取数据还有后端定义接口的方式。

再来理顺一遍GraphQL的内容:一门数据查询语言,仅此而已。前端写GraphQL获取数据,后端写GraphQL,也就是接口文档,并且还要把从数据库传来的数据与GraphQL对接,转换成前端要请求的数据,最大的亮点是前端能够获得一份程序自动生成的api文档。

前端篇

这里推荐一下GraphQL的调试工具:​​Apollo Studio​​ ,在左上角输入后端给你的GraphQL地址就能获得完整的智能提示。

GraphQL对于前端来说学习起来并不难,因为整体结构和json比较相像,而且语法极其简单。这里我举几个例子相信各位看了就懂。

老板最近看了星球大战系列的电影,要前后端一起写一个电影里出现的角色们的增删改查系统。现在前端需要角色们的数据,后端同学告诉前端,英雄列表的接口名叫heros,id和姓名的属性名叫id和name。那GraphQL该怎么写呢?

query getHeros{
heros {
id,name
}
}

获取来的数据如下:

{
"data": {
"heros": [
{
"id": "1",
"name": "laowang"
},
{
"id": "2",
"name": "laoliu"
}
]
}
}

这里来分析下刚才的GraphQL语句:“query”指的是操作类型(operation type),“getHeros”指的是操作名(operation name)。这两个去掉了都不会报错,但是在调试的时候就麻烦了。所以还是要根据业务情景填写恰当的操作类型和操作名。

heros是后端定义好的接口,然后花括号跟接口提供的数据里面的属性名,表示前端只需要写出来的这些属性,其他属性即使有也别发给前端。是不是肥肠简单(#狗头)

现在查到了角色们的id和姓名,就要根据每个角色的id查询角色具体的信息了。那么查询语句就要这样写:

query getHero($heroId: ID!){
hero(id: $heroId) {
id,name
}
}

这里来解释下新的东西:$heroId是指要在请求的json字符串里附带的参数。这两个地方写什么都行,但是要求两个地方的名称一样。这里为了演示就写作heroId,实际工作中还是最好和借接口参数名一致,即id。在发送请求时用浏览器调试工具截取请求为如下内容:

GraphQL教程

ID指的是数据类型,ID在这里是指唯一标识符,可以为数字或者字符串,不过一般都是用字符串。其他的基础类型还有:

  • ​Int​​: A signed 32‐bit integer
  • ​Float​​: A signed double-precision floating-point value
  • ​String​​: A UTF‐8 character sequence
  • ​Boolean​​: ​​true​​ or ​​false​
  • ​ID​​ (serialized as a ​​String​​): A unique identifier that's often used to refetch an object or as the key for a cache. Although it's serialized as a ​​String​​, an ​​ID​​ is not intended to be human‐readable.

​GraphQL schema basics​

hero(id: $heroId) { 这里的id指的就是后台给你的接口参数名,不能乱填。

这样我们已经实现了查询功能,还有增删改,这一部分基本和查询差不多,主要的区别在于操作类由之前的"query"改为了"mutation"。

比如要新增一个角色,那么查询语句就该这么写:

mutation addHero($name: String!) {
addHero(name: $name) {
id,name
}
}

调用新增英雄这个接口名字叫addHero(第二行)操作名也叫addHero(第一行),第三行的id和name是要求后端返回新英雄的id和name。addHero接口只需要name一个参数,请求的body部分如下:

GraphQL教程

这样接收到的数据如下:

GraphQL教程

这样我们就新增了一个叫"jiege"的英雄。其他的删、改也和新增一模一样,之是接口名称不同而已,怎么样,前端用GraphQL是不是超简单(#滑稽)

后端篇

后端相对于前端来说难度差不多,引入GraphQL后工作量只增不减,工作流程变成了用sql从数据库获得数据 -> 处理数据 -> 编写GraphQL-> 传给前端。现在我们也是用前端篇的星球大战角色查询的例子给大家讲解。

在开始之前希望后端同学们知道,开发GraphQL的facebook没有公开任何自己的GraphQL后端实现,所以就没有“官方案例”这一说法。官方有提供关于各个语言平台的包和文档,但是不是很好理解,所以这里的后端是用文档写得比较好的​​apollo server​​这个后端来实现的。如果在概念上还不是很懂,可以先从这个文档入手,虽然apollo server的语言是js,但各个平台的思路基本上都是一样的。