什么是GRAPHQL
GraphQL是API的查询语言和运行时,用于使用现有数据完成这些查询。 GraphQL提供了API中数据的完整且易于理解的描述,使客户能够准确地询问他们需要什么,仅此而已,使API随着时间的推移更容易发展,并支持强大的开发人员工具。
GraphQL 与 RESTful 有什么区别?
- 首先放上一张来自于 graphql.org 的图片。REST 与 GraphQL 都是服务端所承载的系统对外的服务接口,因此两者肯定是可以共存的,甚至可以共用一套 Authorization 等业务逻辑。
RESTful的一些不足: - 扩展性,单个RESTful接口返回数据越来越臃肿
比如获取用户信息/users/:id,最初可能只有id、昵称,但随着需求的变化,用户所包含的字段可能会越来越多,年龄、性别、头像、经验、等级,等等等等。
而具体到某个前端页面,可能只需要其中一小部分数据,这样就会增加网络传输量,前端获取了大量不必要的数据。
- 某个前端展现,实际需要调用多个独立的RESTful API才能获取到足够的数据
比如一个文章详情页,最初可能只需要文章内容,那么前端就调用/articles/:aid获取到文章内容来展现就行了
但随着需求的演进,产品可能会希望加上作者信息(昵称、头像等),这时前端又需要在获取文章详情后,根据其中的作者id字段继续获取作者相关的信息,/user/:uid
然后,需求又变化了,产品希望在加上这篇文章的评论,这时前端需要继续调用/comment/:aid来拉取评论列表
对于Web前端而言,由于ajax技术的存在,这种的请求数据方式,也就开发上稍微麻烦些,并不会造成太大的问题;但对于App来说,渲染的方式不同,必须要拉取的全部的数据之后,才能绘制界面,就会导致这个界面必须要等到所有3个RESTful接口的返回数据都拿到,才能进行绘制。
GraphQL的一些优点
- 所见即所得
查询的返回结果就是输入的查询结构的精确映射
查询:1
2
3
4
5
6{
books(id: 3) {
id
name
}
}
返回:
1 | { |
- 减少网络请求次数
如果设计的数据结构是从属的(例如,上文中书的作者信息),直接就能在查询语句中指定:1
2
3
4
5
6
7
8
9
10{
books(id: 3) {
id,
name,
author {
id,
name
}
}
}
即使数据结构是独立的,也可以在查询语句中指定上下文,只需要一次网络请求,就能获得资源和子资源的数据(例如,上文中书和作者信息)
1 | { |
代码即文档
GraphQL会把schema定义和相关的注释生成可视化的文档,从而使得代码的变更,直接就反映到最新的文档上,避免RESTful中手工维护可能会造成代码、文档不一致的问题。参数类型强校验
RESTful方案本身没有对参数的类型做规定,往往都需要自行实现参数的校验机制,以确保安全。
但GraphQL提供了强类型的schema机制,从而天然确保了参数类型的合法性。
GraphQL 能做到修改数据吗?
看了上面的 query 的例子,你肯定很好奇,graphql 这种看上去好像只为查询而存在的语言,是不是有办法做到修改数据呢?
答案是:能。
仅仅为了使得 GraphQL 这个 data platform 变得更加完整,GraphQL 标准中加入了一种操作符,名为 mutation。因为我觉得这种设计确实比较一般,此处就不举例了,详情见:http://graphql.org/learn/queries/#mutations
令人期待的 subscription
如何在浏览器中接受服务端的推送信息是个老生常谈的问题。从最初的轮询,到后来的 WebSocket。如今 GraphQL 也计划引入除了 query, mutation 以外的第三种操作符 subscription,以便于直接接受服务器推送数据。在 2015 年底 GraphQL 官方发布了一篇博文:Subscriptions in GraphQL and Relay 来介绍 subscription 在他们的 iOS 和 Android App 中的应用。可惜的是相关的代码仍未开源,目前开源社区能找到的解决方案目前只有 Apollo 社区为 Node.js 写的 graphql-subscriptions。
GraphQL 有什么缺点?
- N + 1 问题
以下解决方案仅针对关系型数据库,如果你的项目中使用的是 NoSQL,可能解决方案有较大差别。
针对一对一的关系(比如我上面举例中提到的这个 User 与 UserScore 的关系),在从数据库里抓取数据时,就将所需数据 join 到一张表里。别等着 ORM 框架替你懒加载那些你需要的数据。
针对多对一或者多对多的关系,你就要用到一个叫做 DataLoader 的工具库了。其中,Facebook 为 Node.js 社区提供了 DataLoader 的实现。DataLoader 的主要功能是 batching & caching,可以将多次数据库查询的请求合并为一个,同时已经加载过的数据可以直接从 DataLoader 的缓存空间中获取到。这个话题要是展开说也得写一篇新的文章了,此处不多赘述。
有什么可以快乐地调试 GraphQL 接口的方法?
GraphiQL / live demo
使用 GraphiQL 可以很容易地让人感受到“代码即文档”的快乐。
扩展阅读: https://graphql.org/ https://www.howtographql.com/graphql-python/0-introduction/