前几年出现了一个叫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该怎么写呢?
获取来的数据如下:
这里来分析下刚才的GraphQL语句:“query”指的是操作类型(operation type),“getHeros”指的是操作名(operation name)。这两个去掉了都不会报错,但是在调试的时候就麻烦了。所以还是要根据业务情景填写恰当的操作类型和操作名。
heros是后端定义好的接口,然后花括号跟接口提供的数据里面的属性名,表示前端只需要写出来的这些属性,其他属性即使有也别发给前端。是不是肥肠简单(#狗头)
现在查到了角色们的id和姓名,就要根据每个角色的id查询角色具体的信息了。那么查询语句就要这样写:
这里来解释下新的东西:$heroId是指要在请求的json字符串里附带的参数。这两个地方写什么都行,但是要求两个地方的名称一样。这里为了演示就写作heroId,实际工作中还是最好和借接口参数名一致,即id。在发送请求时用浏览器调试工具截取请求为如下内容:
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.
hero(id: $heroId) { 这里的id指的就是后台给你的接口参数名,不能乱填。
这样我们已经实现了查询功能,还有增删改,这一部分基本和查询差不多,主要的区别在于操作类由之前的"query"改为了"mutation"。
比如要新增一个角色,那么查询语句就该这么写:
调用新增英雄这个接口名字叫addHero(第二行)操作名也叫addHero(第一行),第三行的id和name是要求后端返回新英雄的id和name。addHero接口只需要name一个参数,请求的body部分如下:
这样接收到的数据如下:
这样我们就新增了一个叫"jiege"的英雄。其他的删、改也和新增一模一样,之是接口名称不同而已,怎么样,前端用GraphQL是不是超简单(#滑稽)
后端篇
后端相对于前端来说难度差不多,引入GraphQL后工作量只增不减,工作流程变成了用sql从数据库获得数据 -> 处理数据 -> 编写GraphQL-> 传给前端。现在我们也是用前端篇的星球大战角色查询的例子给大家讲解。
在开始之前希望后端同学们知道,开发GraphQL的facebook没有公开任何自己的GraphQL后端实现,所以就没有“官方案例”这一说法。官方有提供关于各个语言平台的包和文档,但是不是很好理解,所以这里的后端是用文档写得比较好的apollo server这个后端来实现的。如果在概念上还不是很懂,可以先从这个文档入手,虽然apollo server的语言是js,但各个平台的思路基本上都是一样的。