在我看来,graphql提供了一种api的解决方案。
以前我们查询api提供的数据是怎么做的呢?
举一个例子,例如现在有这么一个查询书籍信息的接口:/book/info,按照我们之前的解决方案,我们一般会传一个类似book_id的参数到这个接口,然后接口把书籍信息返回给我们
同样的,如果又有一个查询作者信息的需求,那么我们会新增一个接口:/author/info,并以book_id为参数查询作者信息
可以看到,以往我们使用的api查询数据的操作是分散的,彼此之间是没啥联系,查询多个数据就要向不同的接口发送多个请求
但是graphql很特别,它一般只提供一个接口/graphql,所有的数据查询操作都是向此接口发送请求,并且,只需要发送一次请求就可以获得多个数据
那graphql是怎么实现这一点的呢?
这得归功于graphql的面向对象思想
在graphql中,所有的数据形成了一张彼此相互关联的“图”,此处的“图”是指数据结构中的“图”
怕大家忘了啥是图,贴一张图回忆回忆
图论〔GraphTheory〕是数学的一个分支。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。图论是一种表示"多对多"的关系图是由顶点和边组成的:(可以无边,但至少包含一个顶点)
图中的每一个顶点就是咱们的数据,那这些数据是怎么关联起来的呢?
实际上还是借助了面向对象的思想,graphql把每一种数据都给抽象成了一个类,例如咱们上面提到的两个接口,在graphql中,这两个接口背后对应的数据就可以被抽象为Book类以及Author类
但是,这里说的类只是一个概念,区别于咱们编程语言中的类,与其说它是一个类,不如说它是一个结构,在Graphql中,Book类可以这样描述
typeBook{id:IDname:StringpageCount:Intauthor:Author}
Author类:
typeAuthor{id:IDfirstName:StringlastName:Stringbook:Book}
其中Book类有一个属性是author,代表一本书的作者,而Author类中有一个属性是book,表示该作者写过的所有的书,这两个类一下子就产生了联系
如果用图论中的有向图表示这两个顶点,就是下面这个样子:
现在咱们只是对数据做了抽象描述,那么怎么把数据暴露给前端呢?咱们还需要借助一个类型
这个类型就是Query,在Query类中我们可以定义各个查询接口:
typeQuery{bookById(id:ID):BookauthorById(id:ID):Author}
上面就在Query类中定义了两个接口,bookById(id:ID):Book表示对外暴露的接口名为bookById,然后这个接口接受一个参数id,这个id的类型为ID,该接口的返回类型为Book
暴露了接口,我们前端就可以查询了,前端查询的格式也是很讲究的,例如我要查id为book-1的书籍的名字和页数,就可以传如下数据到接口/graphql:
{bookByID(id:"book-1"){name,pageCount}}
如果我要查,id为book-1的书籍的名字以及其作者的名字,可以发送如下格式的数据:
{bookByID(id:"book-1"){name,author{firstName,lastName}}}
返回结果也是很清晰的,如下:
总结起来,graphql的工作流程如下:
当然,这也只是一个整体上的流程,没有涉及到具体的代码实现,其实在写代码的时候还得考虑数据来自哪里,这就涉及到为每个数据类型配置dataFetcher了,具体的代码实现案例可以看