写点什么

GraphQl:让你的接口所得即所要

  • 2022 年 9 月 29 日
    北京
  • 本文字数:3000 字

    阅读完需:约 10 分钟

背景

常见的 RESTful API 中,每个 API 负责请求一种类型的对象,一个页面往往需要多次请求接口,且经常存在依赖关系,无法并行发送请求。在工作中是否经常遇到这个场景:

产品:本次需求我们需要在页面上新增***展示。

前端:目前后端提供的接口中没有返回,需要新增字段。

后端:这个接口现在多方在使用,需要评估是否会对其他使用方有影响,且目前排期已满,需要等到****版本才能做。

产品:Boss 说明天要上线……

如果是个人项目,可能这个需求一两个小时就能完成,但如果是公司项目,这样一个小小的需求,动辄花费的时间要上周才能上线。那么,我们是否可以通过某种手段,将接口的返回值从静态变成动态,即调用者来声明接口返回什么数据,来进一步解耦前后端的关联?于是,Facebook 在 2016 年 9 月,GraphQL 正式进入生产环境。GraphQL 的联合创建者 Dan Schafer 认为:

“GraphQL 是一种查询语言,用于我们在客户端和服务器之间转移合约的 API,允许服务器说‘这些是我公开的能力’,并允许客户端以一种方式来描述它们的要求,而这种方式最终使产品开发人员能够构建其希望创建的产品。”

在后台,它告诉 API 如何把检索到的数据呈现给客户端,是的开发人员能够发出精确的数据请求,不多也不少。

GraphQL 的使用

01

几个重要的概念

https://graphql.cn/learn/queries/
复制代码

GraphQL 的操作类型可以是 query、mutation 或 subscription,描述客户端希望进行什么样的操作

query 查询:获取数据,比如查找,CRUD 中的 R

mutation 变更:对数据进行变更,比如增加、删除、修改,CRUD 中的 CUD

substription 订阅:当数据发生更改,进行消息推送

1.2 对象类型和标量类型 Object Type & Scalar Type

如果一个 GraphQL 服务接受到了一个 query,那么这个 query 将从 Root Query 开始查找,找到对象类型(Object Type)时则使用它的解析函数 Resolver 来获取内容,如果返回的是对象类型则继续使用解析函数获取内容,如果返回的是标量类型(Scalar Type)则结束获取,直到找到最后一个标量类型。

对象类型:用户在 schema 中定义的 type

标量类型:GraphQL 中内置有一些标量类型 String、Int、Float、Boolean、ID,用户也可以定义自己的标量类型。

1.3 模式 Schema

它定义了字段的类型、数据的结构,描述了接口数据请求的规则,当我们进行一些错误的查询的时候 GraphQL 引擎会负责告诉我们哪里有问题,和详细的错误信息,对开发调试十分友好。Schema 使用一个简单的强类型模式语法,称为模式描述语言(Schema Definition Language, SDL)。

02

实战

Python GraphQL 入门示例,采用 Flask 框架,API 使用 GraphQL 实现一个 web 服务,提供书籍的查询与添加功能。

2.1 安装模块

pip install graphenepip install Flask-GraphQLtype Book{    id: ID!    name: String!}
type Query{ books: [Book!]!}
type Mutation{ add(name: String!): Book!}
复制代码

2.3 web 服务

from flask import Flask  from flask_graphql import GraphQLView  import graphene
app = Flask(__name__)
books = []
class Book(graphene.ObjectType): """ Book """
id = graphene.ID(description="book ID")
name = graphene.String(description="book name")
create = lambda id, name: Book(id=id, name=name)
books.append(create(1, "The First Book"))
class Query(graphene.ObjectType): """ query your books """
books = graphene.List(Book, description="list books")
version = graphene.String(description="version")
def resolve_books(self, info): return books
def resolve_version(self, info): return "v0.1"
# Mutation
class AddBook(graphene.Mutation): """ Add books """ Output = Book
class Arguments: name = graphene.String()
def mutate(self, info, name): book = create(len(books) + 1, name) books.append(book) return book
class Mutation(graphene.ObjectType): """ mutate books """ add = AddBook.Field()
schema = graphene.Schema(query=Query, mutation=Mutation)
app.add_url_rule('/graphql', view_func=GraphQLView.as_view('graphql', schema=schema, graphiql=True))
app.run(port=4901, debug=True)
复制代码

① books 是一个全局变量,用于保存所有的 books,可把它当做数据库,很多示例都有数据库,为了保持简单,最方便运行,所以,我只用了这么一个变量

② Query 是比较简单的,语义很清晰,和 API 文档不同的是,在 Query 中增加了一个 version,这是为了简单对比一个 restful ,如果是 restful 的话,我们要获取 books 和 version 这两个资源,需要两个 API,但 graphq 只需要一个

③ Mutation 分为两步,第一步定义一个 Mutate,里面必须要有 mutate 方法,第二个创建 Mutation,用于组合所有的 Mutate。

④ /graphql 是给我们提供一个可视化的 API 展示,类似 Swagger,当然,生产环境就不要加这个了,加在开发、测试环境即可

运行代码:

python server.py

2.4 查询

使用 curl 做测试,大家也可以尝试使用界面,更直观

http://127.0.0.1:4901/graphql\?query\=query%20%7Bbooks%20%7Bid%20name%20%7D%20version%7D
复制代码

总结

我们上面介绍了 GraphQL 的优势,我们也介绍一下它的劣势及讨论一下为什么没有流行起来。

01

第一,Facebook 从来没有公开自己的 GraphQL 后端设计,使得大家必需要用第三方的,但体验显然不如我们在 Facebook 内部使用 GraphQL 好。我上面说了,数据必需已经以图的数据结构进行存储才有优势。Facebook 内部有非常好的后端做好了这件事情,而且还内置了基于隐私设置的访问控制。例如说你发的帖子有些是所有人可见的、有些是好友可见的、有些是仅同事可见的,我在打开你的页面时 Facebook 有一个中间层保证了根据我和你的关系我只能看到我该看到的帖子。GraphQL 在这一层之上,所以无论 GraphQL 怎么写我都不可能看到我不该看到的信息。

02

第二,并不是所有场景都适用于 GraphQL 的,有些很简单的事情就应该用 RESTful API 来实现。Facebook 内部用户增长部门的很多 API 都还不是 GraphQL,因为没必要迁移到 GraphQL。用户增长部门的 API 处理新用户注册、填写短信验证码之类的事情,这些事情都是围绕着一个用户的具体某项或多项信息发生的,根本没有任何图的概念。可以强行写作 GraphQL,但得不到显著的好处。既然老的 API 早就写好了,需要的时候做一些小改动,但没必要重写。

03

第三,GraphQL 尽管查询的数据是图状数据结构,但实际获得的数据视图是树状数据结构。每一个 GraphQL 查询或更新都有自己的根节点,然后所有的数据都是从根结点展开出去的。查询后获得的数据如果要在前端重新变回图的状态,那前端就不能简单地缓存查询得到的数据,必须用对用的 GraphQL 存储库,然后通过顶点的 ID 把不同节点之间的某些边重新连接起来。

而其没有流行起来的原因主要在于,GraphQL 的利好主要是在于前端的开发效率,但落地却需要服务端的全力配合。如果是小公司或者整个公司都是全栈,那可能可以做,但在很多前后端分工比较明确的团队里,要推动 GraphQL 还是会遇到各种协作上的阻力。

更多学习资料戳下方!!!

https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=infoQ&timestamp=1662366626&author=xueqi

用户头像

社区:ceshiren.com 2022.08.29 加入

微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料、实事更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬

评论

发布
暂无评论
GraphQl:让你的接口所得即所要_测试_测吧(北京)科技有限公司_InfoQ写作社区