Restful
目前大多数网站都基于Restful架构,在该模式下,每个资源都有自己配套的一个API接口。用URI来定位资源,Method来描述对资源做什么操作。
现在在该模式下,我们有这样一个需求:显示一篇文章的内容,同时也要显示评论、作者信息。那么我们就需要分别调用文章接口、评论接口、用户接口。该架构就会暴露出一些缺陷:
1.多消耗客户端资源:调用多个API接口,多次发送HTTP请求,并且需要在用户端进行信息拼接。
2.冗余数据:比如我们可能只要知道用户姓名,但是用户接口可能会一起返回性别,星座等无关数据。
3.字段类型校验:由于服务端返回数据的不可控性,前端需要对某些字段做类型校验。
4.接口文档不规范:前后端分离开发约定的接口文档,可能会因为后端开发的疏忽更新不及时,引发后续问题。
而GraphQL能完美的解决上述问题。
GraphQL
官方定义
我们先来看一下GraphQL的官方定义:
简直晦涩难懂...我们还是直接来看看同一个需求,在GraphQL架构下的实现吧~
同一个需求,在GraphQL下的实现
首先我们访问GraphQL服务器,点击SCHMA查看一下它提供给前端什么资源。比如用户资源,获取时需携带用户ID,返回的User对象可取字段有id,name等。接着就可以写请求SCHEMA,获取定制化数据(项目代码在附录章节)
演示:graphql.mov
Restful vs GraphQL
GraphQL几个重要概念
操作类型 Operation Type
- 描述客户端希望进行什么样的操作
1.query 查询:获取数据,比如查找,CRUD 中的 R。
2.mutation 变更:对数据进行变更,比如增加、删除、修改,CRUD 中的 CUD。
3.substription 订阅:当数据发生更改,进行消息推送。
对象类型和标量类型 Object Type & Scalar Type
- 定义资源
1.对象类型:用户在 schema 中定义的 type。
2.标量类型:GraphQL 中内置有一些标量类型 String、Int、Float、Boolean、ID,
用户也可以定义自己的标量类型。
解析函数 Resolver
- 服务端提供资源的方式
前端请求信息到达后端之后,需要由解析函数 Resolver 来提供数据。
GraphQL使用流程
Describe your data - 服务端要做的事
1.定义资源结构。
2.定义每个操作类型下暴露给前端的资源或接口。
3.为每个操作类型下的资源或接口提供Resolve策略函数。
Query
Mutation
Subscription
这里的 pubsub
是 apollo-server 里负责订阅和发布的类,它在接受订阅时提供一个异步迭代器,在后端觉得需要发布订阅的时候向前端发布 payload。withFilter
的作用是过滤掉不需要的订阅消息,详细用法参照订阅过滤器。
Ask for what you want - 前端如何请求资源
1.查询资源
2.更新资源
3.订阅资源
发送一个订阅请求
发送一个更新请求,触发订阅
触发之前定义的逻辑
Get predictable results - 通过HTTP协议交互
以之前的Query请求为例:
小结
2.客户端发送一个带有查询语句(graphql的查询协议)的请求,请求里定义了需要哪些数据。
3.服务端返回给客户端符合客户端预期的json字符串结果。
GraphQL个人理解
对前端而言,GraphQL就是一套和GraphQL服务器上资源进行交互的语法。(即如何去写schema)
对后端而言, GraphQL就是一套提供资源的策略,告知前端每个资源的形态和操作方式,前端按需组装。(即如何为schema提供数据)
GraphQL运行机制
1.请求传输 - HTTP Request
客户端通过HTTP协议,将Schema封装在body中,传输到GraphQL服务器。
2.解析阶段 - String -> document
识别 Schema 字符串。graphql-js利用特征标识符与 AST 语法树规范,对 Schema 逐字符扫描,通过词法分析和语法分析得到节点树。
特征标识符:
AST 语法树规范,规定语法树支持以下节点:
最终解析阶段的产出物 - document:
3.校验阶段 - 检验document
验证客户端 Schema 是否按照服务端定义好的方式获取数据,比如:获取数据的方法名是否有误,必填项是否有值等。
4.执行阶段 - document -> json
执行对应的 resolve 函数,封装成json资源并输出。
每个类型的每个字段都有一个resolver函数支持,该函数由GraphQL服务器开发人员提供,当一个字段被执行时,相应的resolver被调用产生下一个值。如果字段产生标量值,则执行完成,如果产生对象,则该查询将继续执行该对象对应的解析器,直到返回标量值。
5.响应返回 - HTTP Response
GraphQL开源协议
BSD+Patents
graphql-js曾经用过BSD+Patents协议。
Patents:专利附属条款,被视为Facebook用于解决开源代码中可能出现的专利纠纷的防御措施。
大致内容是使用基于Patents协议的开源项目的开发者,未来要是因为专利问题与Facebook产生纠纷,那么Facebook将有权停止你使用该开源项目,也就是说如果你起诉Facebook,那么你所使用他们的开源技术开发的产品要么得停用,要么得用别的技术迁移重构。
MIT
在2017年移除,改为MIT并沿用至今。
事件背景:2017年7月,开源组织 Apache 软件基金会将基于Facebook BSD+Patents协议的开源软件列入黑名单,同年9月,WordPress、百度等大型公司宣布停用React(Native)开源项目以规避风险,此后,Facebook才公开发表声明,表示从 v16开始,React将不再使用BSD+Patents协议,而是采用MIT协议。
在这之后, Facebook逐渐把很多开源项目改为MIT协议。
专利
目前GraphQL的专利还在Facebook手里,要到 2034 年才过期。所以目前部门只在运营管理端接入,开发者管理端因为安全问题暂时还没有接入计划。
附录
项目地址:
Github
参考: